Skip to content

Commit 5f4e6fb

Browse files
committed
add tests and initial fix
1 parent 9f1983d commit 5f4e6fb

File tree

5 files changed

+69
-2
lines changed

5 files changed

+69
-2
lines changed

src/compiler/checker.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26672,11 +26672,22 @@ namespace ts {
2667226672
const func = getContainingFunction(node);
2667326673
if (func) {
2667426674
const functionFlags = getFunctionFlags(func);
26675-
const contextualReturnType = getContextualReturnType(func);
26675+
let contextualReturnType = getContextualReturnType(func);
2667626676
if (contextualReturnType) {
26677+
const isAsyncGenerator = (functionFlags & FunctionFlags.Async) !== 0;
26678+
if (!node.asteriskToken && contextualReturnType.flags & TypeFlags.Union) {
26679+
contextualReturnType = filterType(contextualReturnType, type => {
26680+
// >> What should we use to filter?
26681+
// >> What will be the perf impacts? Is there caching? Is it enough to make this ok?
26682+
// return !!getIterationTypeOfGeneratorFunctionReturnType(IterationTypeKind.Yield, type, isAsyncGenerator);
26683+
// >> ^^^ doesn't work, because we get { yield: any, return: any } for bogus types
26684+
const generator = createGeneratorReturnType(anyType, anyType, anyType, isAsyncGenerator);
26685+
return checkTypeAssignableTo(generator, type, /*errorNode*/ undefined);
26686+
});
26687+
} // >> TODO: should we do something when `node.asteriskToken`?
2667726688
return node.asteriskToken
2667826689
? contextualReturnType
26679-
: getIterationTypeOfGeneratorFunctionReturnType(IterationTypeKind.Yield, contextualReturnType, (functionFlags & FunctionFlags.Async) !== 0);
26690+
: getIterationTypeOfGeneratorFunctionReturnType(IterationTypeKind.Yield, contextualReturnType, isAsyncGenerator);
2668026691
}
2668126692
}
2668226693

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
//// [contextualTypeOnYield.ts]
2+
type FuncOrGeneratorFunc = () => (number | Generator<(arg: number) => void, any, void>)
3+
4+
const f: FuncOrGeneratorFunc = function*() {
5+
yield (num) => console.log(num); // `num` should be inferred to have type `number`.
6+
}
7+
8+
//// [contextualTypeOnYield.js]
9+
"use strict";
10+
const f = function* () {
11+
yield (num) => console.log(num); // `num` should be inferred to have type `number`.
12+
};
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
=== tests/cases/compiler/contextualTypeOnYield.ts ===
2+
type FuncOrGeneratorFunc = () => (number | Generator<(arg: number) => void, any, void>)
3+
>FuncOrGeneratorFunc : Symbol(FuncOrGeneratorFunc, Decl(contextualTypeOnYield.ts, 0, 0))
4+
>Generator : Symbol(Generator, Decl(lib.es2015.generator.d.ts, --, --))
5+
>arg : Symbol(arg, Decl(contextualTypeOnYield.ts, 0, 54))
6+
7+
const f: FuncOrGeneratorFunc = function*() {
8+
>f : Symbol(f, Decl(contextualTypeOnYield.ts, 2, 5))
9+
>FuncOrGeneratorFunc : Symbol(FuncOrGeneratorFunc, Decl(contextualTypeOnYield.ts, 0, 0))
10+
11+
yield (num) => console.log(num); // `num` should be inferred to have type `number`.
12+
>num : Symbol(num, Decl(contextualTypeOnYield.ts, 3, 9))
13+
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
14+
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
15+
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
16+
>num : Symbol(num, Decl(contextualTypeOnYield.ts, 3, 9))
17+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
=== tests/cases/compiler/contextualTypeOnYield.ts ===
2+
type FuncOrGeneratorFunc = () => (number | Generator<(arg: number) => void, any, void>)
3+
>FuncOrGeneratorFunc : () => number | Generator<(arg: number) => void, any, void>
4+
>arg : number
5+
6+
const f: FuncOrGeneratorFunc = function*() {
7+
>f : FuncOrGeneratorFunc
8+
>function*() { yield (num) => console.log(num); // `num` should be inferred to have type `number`.} : () => Generator<(num: number) => void, void, any>
9+
10+
yield (num) => console.log(num); // `num` should be inferred to have type `number`.
11+
>yield (num) => console.log(num) : any
12+
>(num) => console.log(num) : (num: number) => void
13+
>num : number
14+
>console.log(num) : void
15+
>console.log : (...data: any[]) => void
16+
>console : Console
17+
>log : (...data: any[]) => void
18+
>num : number
19+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// @strict: true
2+
// @target: ES6
3+
4+
type FuncOrGeneratorFunc = () => (number | Generator<(arg: number) => void, any, void>)
5+
6+
const f: FuncOrGeneratorFunc = function*() {
7+
yield (num) => console.log(num); // `num` should be inferred to have type `number`.
8+
}

0 commit comments

Comments
 (0)