Skip to content

Commit e955108

Browse files
committed
fix return statement contextual typing
1 parent 156d7a8 commit e955108

9 files changed

+70
-15
lines changed

src/compiler/checker.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26638,6 +26638,12 @@ namespace ts {
2663826638
if (contextualReturnType) {
2663926639
const functionFlags = getFunctionFlags(func);
2664026640
if (functionFlags & FunctionFlags.Generator) { // Generator or AsyncGenerator function
26641+
if (contextualReturnType.flags & TypeFlags.Union) {
26642+
contextualReturnType = filterType(contextualReturnType, type => {
26643+
const generator = createGeneratorReturnType(anyType, anyType, anyType, (functionFlags & FunctionFlags.Async) !== 0);
26644+
return checkTypeAssignableTo(generator, type, /*errorNode*/ undefined);
26645+
});
26646+
}
2664126647
const iterationReturnType = getIterationTypeOfGeneratorFunctionReturnType(IterationTypeKind.Return, contextualReturnType, (functionFlags & FunctionFlags.Async) !== 0);
2664226648
if (!iterationReturnType) {
2664326649
return undefined;
@@ -26676,14 +26682,10 @@ namespace ts {
2667626682
const isAsyncGenerator = (functionFlags & FunctionFlags.Async) !== 0;
2667726683
if (!node.asteriskToken && contextualReturnType.flags & TypeFlags.Union) {
2667826684
contextualReturnType = filterType(contextualReturnType, type => {
26679-
// >> What should we use to filter?
26680-
// >> What will be the perf impacts? Is there caching? Is it enough to make this ok?
26681-
// return !!getIterationTypeOfGeneratorFunctionReturnType(IterationTypeKind.Yield, type, isAsyncGenerator);
26682-
// >> ^^^ doesn't work, because we get { yield: any, return: any } for bogus types
2668326685
const generator = createGeneratorReturnType(anyType, anyType, anyType, isAsyncGenerator);
2668426686
return checkTypeAssignableTo(generator, type, /*errorNode*/ undefined);
2668526687
});
26686-
} // >> TODO: should we do something when `node.asteriskToken`?
26688+
}
2668726689
return node.asteriskToken
2668826690
? contextualReturnType
2668926691
: getIterationTypeOfGeneratorFunctionReturnType(IterationTypeKind.Yield, contextualReturnType, isAsyncGenerator);

tests/baselines/reference/contextualTypeOnYield.js renamed to tests/baselines/reference/contextualTypeOnYield1.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
//// [contextualTypeOnYield.ts]
1+
//// [contextualTypeOnYield1.ts]
22
type FuncOrGeneratorFunc = () => (number | Generator<(arg: number) => void, any, void>)
33

44
const f: FuncOrGeneratorFunc = function*() {
55
yield (num) => console.log(num); // `num` should be inferred to have type `number`.
66
}
77

8-
//// [contextualTypeOnYield.js]
8+
//// [contextualTypeOnYield1.js]
99
"use strict";
1010
const f = function* () {
1111
yield (num) => console.log(num); // `num` should be inferred to have type `number`.
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
1-
=== tests/cases/compiler/contextualTypeOnYield.ts ===
1+
=== tests/cases/compiler/contextualTypeOnYield1.ts ===
22
type FuncOrGeneratorFunc = () => (number | Generator<(arg: number) => void, any, void>)
3-
>FuncOrGeneratorFunc : Symbol(FuncOrGeneratorFunc, Decl(contextualTypeOnYield.ts, 0, 0))
3+
>FuncOrGeneratorFunc : Symbol(FuncOrGeneratorFunc, Decl(contextualTypeOnYield1.ts, 0, 0))
44
>Generator : Symbol(Generator, Decl(lib.es2015.generator.d.ts, --, --))
5-
>arg : Symbol(arg, Decl(contextualTypeOnYield.ts, 0, 54))
5+
>arg : Symbol(arg, Decl(contextualTypeOnYield1.ts, 0, 54))
66

77
const f: FuncOrGeneratorFunc = function*() {
8-
>f : Symbol(f, Decl(contextualTypeOnYield.ts, 2, 5))
9-
>FuncOrGeneratorFunc : Symbol(FuncOrGeneratorFunc, Decl(contextualTypeOnYield.ts, 0, 0))
8+
>f : Symbol(f, Decl(contextualTypeOnYield1.ts, 2, 5))
9+
>FuncOrGeneratorFunc : Symbol(FuncOrGeneratorFunc, Decl(contextualTypeOnYield1.ts, 0, 0))
1010

1111
yield (num) => console.log(num); // `num` should be inferred to have type `number`.
12-
>num : Symbol(num, Decl(contextualTypeOnYield.ts, 3, 9))
12+
>num : Symbol(num, Decl(contextualTypeOnYield1.ts, 3, 9))
1313
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
1414
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
1515
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
16-
>num : Symbol(num, Decl(contextualTypeOnYield.ts, 3, 9))
16+
>num : Symbol(num, Decl(contextualTypeOnYield1.ts, 3, 9))
1717
}

tests/baselines/reference/contextualTypeOnYield.types renamed to tests/baselines/reference/contextualTypeOnYield1.types

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
=== tests/cases/compiler/contextualTypeOnYield.ts ===
1+
=== tests/cases/compiler/contextualTypeOnYield1.ts ===
22
type FuncOrGeneratorFunc = () => (number | Generator<(arg: number) => void, any, void>)
33
>FuncOrGeneratorFunc : () => number | Generator<(arg: number) => void, any, void>
44
>arg : number
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
//// [contextualTypeOnYield2.ts]
2+
type OrGen = () => (number | Generator<string, (arg: number) => void, undefined>);
3+
const g: OrGen = function* () {
4+
return (num) => console.log(num);
5+
}
6+
7+
//// [contextualTypeOnYield2.js]
8+
"use strict";
9+
const g = function* () {
10+
return (num) => console.log(num);
11+
};
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
=== tests/cases/compiler/contextualTypeOnYield2.ts ===
2+
type OrGen = () => (number | Generator<string, (arg: number) => void, undefined>);
3+
>OrGen : Symbol(OrGen, Decl(contextualTypeOnYield2.ts, 0, 0))
4+
>Generator : Symbol(Generator, Decl(lib.es2015.generator.d.ts, --, --))
5+
>arg : Symbol(arg, Decl(contextualTypeOnYield2.ts, 0, 48))
6+
7+
const g: OrGen = function* () {
8+
>g : Symbol(g, Decl(contextualTypeOnYield2.ts, 1, 5))
9+
>OrGen : Symbol(OrGen, Decl(contextualTypeOnYield2.ts, 0, 0))
10+
11+
return (num) => console.log(num);
12+
>num : Symbol(num, Decl(contextualTypeOnYield2.ts, 2, 12))
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(contextualTypeOnYield2.ts, 2, 12))
17+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
=== tests/cases/compiler/contextualTypeOnYield2.ts ===
2+
type OrGen = () => (number | Generator<string, (arg: number) => void, undefined>);
3+
>OrGen : () => number | Generator<string, (arg: number) => void, undefined>
4+
>arg : number
5+
6+
const g: OrGen = function* () {
7+
>g : OrGen
8+
>function* () { return (num) => console.log(num);} : () => Generator<never, (num: number) => void, any>
9+
10+
return (num) => console.log(num);
11+
>(num) => console.log(num) : (num: number) => void
12+
>num : number
13+
>console.log(num) : void
14+
>console.log : (...data: any[]) => void
15+
>console : Console
16+
>log : (...data: any[]) => void
17+
>num : number
18+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// @strict: true
2+
// @target: ES6
3+
4+
type OrGen = () => (number | Generator<string, (arg: number) => void, undefined>);
5+
const g: OrGen = function* () {
6+
return (num) => console.log(num);
7+
}

0 commit comments

Comments
 (0)