Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit bdb8514

Browse files
authoredAug 5, 2022
Fix contextual typing on yield and return expressions in generator function (microsoft#49736)
* add tests and initial fix * fix contextual return type in generator funcs * fix return statement contextual typing * filter using getiterationtypeofgeneratorfunctionreturntype * update baselines
1 parent 5c1abd3 commit bdb8514

14 files changed

+304
-19
lines changed
 

‎src/compiler/checker.ts

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26821,12 +26821,15 @@ namespace ts {
2682126821
if (contextualReturnType) {
2682226822
const functionFlags = getFunctionFlags(func);
2682326823
if (functionFlags & FunctionFlags.Generator) { // Generator or AsyncGenerator function
26824-
const use = functionFlags & FunctionFlags.Async ? IterationUse.AsyncGeneratorReturnType : IterationUse.GeneratorReturnType;
26825-
const iterationTypes = getIterationTypesOfIterable(contextualReturnType, use, /*errorNode*/ undefined);
26826-
if (!iterationTypes) {
26824+
const isAsyncGenerator = (functionFlags & FunctionFlags.Async) !== 0;
26825+
if (contextualReturnType.flags & TypeFlags.Union) {
26826+
contextualReturnType = filterType(contextualReturnType, type => !!getIterationTypeOfGeneratorFunctionReturnType(IterationTypeKind.Return, type, isAsyncGenerator));
26827+
}
26828+
const iterationReturnType = getIterationTypeOfGeneratorFunctionReturnType(IterationTypeKind.Return, contextualReturnType, (functionFlags & FunctionFlags.Async) !== 0);
26829+
if (!iterationReturnType) {
2682726830
return undefined;
2682826831
}
26829-
contextualReturnType = iterationTypes.returnType;
26832+
contextualReturnType = iterationReturnType;
2683026833
// falls through to unwrap Promise for AsyncGenerators
2683126834
}
2683226835

@@ -26855,11 +26858,15 @@ namespace ts {
2685526858
const func = getContainingFunction(node);
2685626859
if (func) {
2685726860
const functionFlags = getFunctionFlags(func);
26858-
const contextualReturnType = getContextualReturnType(func, contextFlags);
26861+
let contextualReturnType = getContextualReturnType(func, contextFlags);
2685926862
if (contextualReturnType) {
26863+
const isAsyncGenerator = (functionFlags & FunctionFlags.Async) !== 0;
26864+
if (!node.asteriskToken && contextualReturnType.flags & TypeFlags.Union) {
26865+
contextualReturnType = filterType(contextualReturnType, type => !!getIterationTypeOfGeneratorFunctionReturnType(IterationTypeKind.Return, type, isAsyncGenerator));
26866+
}
2686026867
return node.asteriskToken
2686126868
? contextualReturnType
26862-
: getIterationTypeOfGeneratorFunctionReturnType(IterationTypeKind.Yield, contextualReturnType, (functionFlags & FunctionFlags.Async) !== 0);
26869+
: getIterationTypeOfGeneratorFunctionReturnType(IterationTypeKind.Yield, contextualReturnType, isAsyncGenerator);
2686326870
}
2686426871
}
2686526872

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
//// [contextualTypeOnYield1.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+
//// [contextualTypeOnYield1.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/contextualTypeOnYield1.ts ===
2+
type FuncOrGeneratorFunc = () => (number | Generator<(arg: number) => void, any, void>)
3+
>FuncOrGeneratorFunc : Symbol(FuncOrGeneratorFunc, Decl(contextualTypeOnYield1.ts, 0, 0))
4+
>Generator : Symbol(Generator, Decl(lib.es2015.generator.d.ts, --, --))
5+
>arg : Symbol(arg, Decl(contextualTypeOnYield1.ts, 0, 54))
6+
7+
const f: FuncOrGeneratorFunc = function*() {
8+
>f : Symbol(f, Decl(contextualTypeOnYield1.ts, 2, 5))
9+
>FuncOrGeneratorFunc : Symbol(FuncOrGeneratorFunc, Decl(contextualTypeOnYield1.ts, 0, 0))
10+
11+
yield (num) => console.log(num); // `num` should be inferred to have type `number`.
12+
>num : Symbol(num, Decl(contextualTypeOnYield1.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(contextualTypeOnYield1.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/contextualTypeOnYield1.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, unknown>
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: 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, unknown>
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: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,53 @@
1-
tests/cases/conformance/generators/generatorReturnContextualType.ts(17,3): error TS2322: Type '{ x: string; }' is not assignable to type '{ x: "x"; }'.
1+
tests/cases/conformance/generators/generatorReturnContextualType.ts(29,3): error TS2322: Type '{ x: string; }' is not assignable to type '{ x: "x"; }'.
2+
Types of property 'x' are incompatible.
3+
Type 'string' is not assignable to type '"x"'.
4+
tests/cases/conformance/generators/generatorReturnContextualType.ts(34,3): error TS2322: Type '{ x: string; }' is not assignable to type '{ x: "x"; }'.
25
Types of property 'x' are incompatible.
36
Type 'string' is not assignable to type '"x"'.
47

58

6-
==== tests/cases/conformance/generators/generatorReturnContextualType.ts (1 errors) ====
9+
==== tests/cases/conformance/generators/generatorReturnContextualType.ts (2 errors) ====
710
// #35995
811

912
function* f1(): Generator<any, { x: 'x' }, any> {
1013
return { x: 'x' };
1114
}
1215

16+
function* g1(): Iterator<any, { x: 'x' }, any> {
17+
return { x: 'x' };
18+
}
19+
1320
async function* f2(): AsyncGenerator<any, { x: 'x' }, any> {
1421
return { x: 'x' };
1522
}
1623

24+
async function* g2(): AsyncIterator<any, { x: 'x' }, any> {
25+
return { x: 'x' };
26+
}
27+
1728
async function* f3(): AsyncGenerator<any, { x: 'x' }, any> {
1829
return Promise.resolve({ x: 'x' });
1930
}
2031

32+
async function* g3(): AsyncIterator<any, { x: 'x' }, any> {
33+
return Promise.resolve({ x: 'x' });
34+
}
35+
2136
async function* f4(): AsyncGenerator<any, { x: 'x' }, any> {
2237
const ret = { x: 'x' };
2338
return Promise.resolve(ret); // Error
2439
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2540
!!! error TS2322: Type '{ x: string; }' is not assignable to type '{ x: "x"; }'.
2641
!!! error TS2322: Types of property 'x' are incompatible.
42+
!!! error TS2322: Type 'string' is not assignable to type '"x"'.
43+
}
44+
45+
async function* g4(): AsyncIterator<any, { x: 'x' }, any> {
46+
const ret = { x: 'x' };
47+
return Promise.resolve(ret); // Error
48+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
49+
!!! error TS2322: Type '{ x: string; }' is not assignable to type '{ x: "x"; }'.
50+
!!! error TS2322: Types of property 'x' are incompatible.
2751
!!! error TS2322: Type 'string' is not assignable to type '"x"'.
2852
}
2953

‎tests/baselines/reference/generatorReturnContextualType.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,35 @@ function* f1(): Generator<any, { x: 'x' }, any> {
55
return { x: 'x' };
66
}
77

8+
function* g1(): Iterator<any, { x: 'x' }, any> {
9+
return { x: 'x' };
10+
}
11+
812
async function* f2(): AsyncGenerator<any, { x: 'x' }, any> {
913
return { x: 'x' };
1014
}
1115

16+
async function* g2(): AsyncIterator<any, { x: 'x' }, any> {
17+
return { x: 'x' };
18+
}
19+
1220
async function* f3(): AsyncGenerator<any, { x: 'x' }, any> {
1321
return Promise.resolve({ x: 'x' });
1422
}
1523

24+
async function* g3(): AsyncIterator<any, { x: 'x' }, any> {
25+
return Promise.resolve({ x: 'x' });
26+
}
27+
1628
async function* f4(): AsyncGenerator<any, { x: 'x' }, any> {
1729
const ret = { x: 'x' };
1830
return Promise.resolve(ret); // Error
1931
}
32+
33+
async function* g4(): AsyncIterator<any, { x: 'x' }, any> {
34+
const ret = { x: 'x' };
35+
return Promise.resolve(ret); // Error
36+
}
2037

2138

2239
//// [generatorReturnContextualType.js]
@@ -25,13 +42,26 @@ async function* f4(): AsyncGenerator<any, { x: 'x' }, any> {
2542
function* f1() {
2643
return { x: 'x' };
2744
}
45+
function* g1() {
46+
return { x: 'x' };
47+
}
2848
async function* f2() {
2949
return { x: 'x' };
3050
}
51+
async function* g2() {
52+
return { x: 'x' };
53+
}
3154
async function* f3() {
3255
return Promise.resolve({ x: 'x' });
3356
}
57+
async function* g3() {
58+
return Promise.resolve({ x: 'x' });
59+
}
3460
async function* f4() {
3561
const ret = { x: 'x' };
3662
return Promise.resolve(ret); // Error
3763
}
64+
async function* g4() {
65+
const ret = { x: 'x' };
66+
return Promise.resolve(ret); // Error
67+
}

‎tests/baselines/reference/generatorReturnContextualType.symbols

Lines changed: 57 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,40 +10,86 @@ function* f1(): Generator<any, { x: 'x' }, any> {
1010
>x : Symbol(x, Decl(generatorReturnContextualType.ts, 3, 10))
1111
}
1212

13+
function* g1(): Iterator<any, { x: 'x' }, any> {
14+
>g1 : Symbol(g1, Decl(generatorReturnContextualType.ts, 4, 1))
15+
>Iterator : Symbol(Iterator, Decl(lib.es2015.iterable.d.ts, --, --))
16+
>x : Symbol(x, Decl(generatorReturnContextualType.ts, 6, 31))
17+
18+
return { x: 'x' };
19+
>x : Symbol(x, Decl(generatorReturnContextualType.ts, 7, 10))
20+
}
21+
1322
async function* f2(): AsyncGenerator<any, { x: 'x' }, any> {
14-
>f2 : Symbol(f2, Decl(generatorReturnContextualType.ts, 4, 1))
23+
>f2 : Symbol(f2, Decl(generatorReturnContextualType.ts, 8, 1))
1524
>AsyncGenerator : Symbol(AsyncGenerator, Decl(lib.es2018.asyncgenerator.d.ts, --, --))
16-
>x : Symbol(x, Decl(generatorReturnContextualType.ts, 6, 43))
25+
>x : Symbol(x, Decl(generatorReturnContextualType.ts, 10, 43))
1726

1827
return { x: 'x' };
19-
>x : Symbol(x, Decl(generatorReturnContextualType.ts, 7, 10))
28+
>x : Symbol(x, Decl(generatorReturnContextualType.ts, 11, 10))
29+
}
30+
31+
async function* g2(): AsyncIterator<any, { x: 'x' }, any> {
32+
>g2 : Symbol(g2, Decl(generatorReturnContextualType.ts, 12, 1))
33+
>AsyncIterator : Symbol(AsyncIterator, Decl(lib.es2018.asynciterable.d.ts, --, --))
34+
>x : Symbol(x, Decl(generatorReturnContextualType.ts, 14, 42))
35+
36+
return { x: 'x' };
37+
>x : Symbol(x, Decl(generatorReturnContextualType.ts, 15, 10))
2038
}
2139

2240
async function* f3(): AsyncGenerator<any, { x: 'x' }, any> {
23-
>f3 : Symbol(f3, Decl(generatorReturnContextualType.ts, 8, 1))
41+
>f3 : Symbol(f3, Decl(generatorReturnContextualType.ts, 16, 1))
2442
>AsyncGenerator : Symbol(AsyncGenerator, Decl(lib.es2018.asyncgenerator.d.ts, --, --))
25-
>x : Symbol(x, Decl(generatorReturnContextualType.ts, 10, 43))
43+
>x : Symbol(x, Decl(generatorReturnContextualType.ts, 18, 43))
44+
45+
return Promise.resolve({ x: 'x' });
46+
>Promise.resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
47+
>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2018.promise.d.ts, --, --))
48+
>resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
49+
>x : Symbol(x, Decl(generatorReturnContextualType.ts, 19, 26))
50+
}
51+
52+
async function* g3(): AsyncIterator<any, { x: 'x' }, any> {
53+
>g3 : Symbol(g3, Decl(generatorReturnContextualType.ts, 20, 1))
54+
>AsyncIterator : Symbol(AsyncIterator, Decl(lib.es2018.asynciterable.d.ts, --, --))
55+
>x : Symbol(x, Decl(generatorReturnContextualType.ts, 22, 42))
2656

2757
return Promise.resolve({ x: 'x' });
2858
>Promise.resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
2959
>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2018.promise.d.ts, --, --))
3060
>resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
31-
>x : Symbol(x, Decl(generatorReturnContextualType.ts, 11, 26))
61+
>x : Symbol(x, Decl(generatorReturnContextualType.ts, 23, 26))
3262
}
3363

3464
async function* f4(): AsyncGenerator<any, { x: 'x' }, any> {
35-
>f4 : Symbol(f4, Decl(generatorReturnContextualType.ts, 12, 1))
65+
>f4 : Symbol(f4, Decl(generatorReturnContextualType.ts, 24, 1))
3666
>AsyncGenerator : Symbol(AsyncGenerator, Decl(lib.es2018.asyncgenerator.d.ts, --, --))
37-
>x : Symbol(x, Decl(generatorReturnContextualType.ts, 14, 43))
67+
>x : Symbol(x, Decl(generatorReturnContextualType.ts, 26, 43))
68+
69+
const ret = { x: 'x' };
70+
>ret : Symbol(ret, Decl(generatorReturnContextualType.ts, 27, 7))
71+
>x : Symbol(x, Decl(generatorReturnContextualType.ts, 27, 15))
72+
73+
return Promise.resolve(ret); // Error
74+
>Promise.resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
75+
>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2018.promise.d.ts, --, --))
76+
>resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
77+
>ret : Symbol(ret, Decl(generatorReturnContextualType.ts, 27, 7))
78+
}
79+
80+
async function* g4(): AsyncIterator<any, { x: 'x' }, any> {
81+
>g4 : Symbol(g4, Decl(generatorReturnContextualType.ts, 29, 1))
82+
>AsyncIterator : Symbol(AsyncIterator, Decl(lib.es2018.asynciterable.d.ts, --, --))
83+
>x : Symbol(x, Decl(generatorReturnContextualType.ts, 31, 42))
3884

3985
const ret = { x: 'x' };
40-
>ret : Symbol(ret, Decl(generatorReturnContextualType.ts, 15, 7))
41-
>x : Symbol(x, Decl(generatorReturnContextualType.ts, 15, 15))
86+
>ret : Symbol(ret, Decl(generatorReturnContextualType.ts, 32, 7))
87+
>x : Symbol(x, Decl(generatorReturnContextualType.ts, 32, 15))
4288

4389
return Promise.resolve(ret); // Error
4490
>Promise.resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
4591
>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2018.promise.d.ts, --, --))
4692
>resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
47-
>ret : Symbol(ret, Decl(generatorReturnContextualType.ts, 15, 7))
93+
>ret : Symbol(ret, Decl(generatorReturnContextualType.ts, 32, 7))
4894
}
4995

‎tests/baselines/reference/generatorReturnContextualType.types

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,16 @@ function* f1(): Generator<any, { x: 'x' }, any> {
1111
>'x' : "x"
1212
}
1313

14+
function* g1(): Iterator<any, { x: 'x' }, any> {
15+
>g1 : () => Iterator<any, { x: 'x';}, any>
16+
>x : "x"
17+
18+
return { x: 'x' };
19+
>{ x: 'x' } : { x: "x"; }
20+
>x : "x"
21+
>'x' : "x"
22+
}
23+
1424
async function* f2(): AsyncGenerator<any, { x: 'x' }, any> {
1525
>f2 : () => AsyncGenerator<any, { x: 'x';}, any>
1626
>x : "x"
@@ -21,6 +31,16 @@ async function* f2(): AsyncGenerator<any, { x: 'x' }, any> {
2131
>'x' : "x"
2232
}
2333

34+
async function* g2(): AsyncIterator<any, { x: 'x' }, any> {
35+
>g2 : () => AsyncIterator<any, { x: 'x';}, any>
36+
>x : "x"
37+
38+
return { x: 'x' };
39+
>{ x: 'x' } : { x: "x"; }
40+
>x : "x"
41+
>'x' : "x"
42+
}
43+
2444
async function* f3(): AsyncGenerator<any, { x: 'x' }, any> {
2545
>f3 : () => AsyncGenerator<any, { x: 'x';}, any>
2646
>x : "x"
@@ -35,6 +55,20 @@ async function* f3(): AsyncGenerator<any, { x: 'x' }, any> {
3555
>'x' : "x"
3656
}
3757

58+
async function* g3(): AsyncIterator<any, { x: 'x' }, any> {
59+
>g3 : () => AsyncIterator<any, { x: 'x';}, any>
60+
>x : "x"
61+
62+
return Promise.resolve({ x: 'x' });
63+
>Promise.resolve({ x: 'x' }) : Promise<{ x: "x"; }>
64+
>Promise.resolve : { (): Promise<void>; <T>(value: T): Promise<Awaited<T>>; <T>(value: T | PromiseLike<T>): Promise<Awaited<T>>; }
65+
>Promise : PromiseConstructor
66+
>resolve : { (): Promise<void>; <T>(value: T): Promise<Awaited<T>>; <T>(value: T | PromiseLike<T>): Promise<Awaited<T>>; }
67+
>{ x: 'x' } : { x: "x"; }
68+
>x : "x"
69+
>'x' : "x"
70+
}
71+
3872
async function* f4(): AsyncGenerator<any, { x: 'x' }, any> {
3973
>f4 : () => AsyncGenerator<any, { x: 'x';}, any>
4074
>x : "x"
@@ -53,3 +87,21 @@ async function* f4(): AsyncGenerator<any, { x: 'x' }, any> {
5387
>ret : { x: string; }
5488
}
5589

90+
async function* g4(): AsyncIterator<any, { x: 'x' }, any> {
91+
>g4 : () => AsyncIterator<any, { x: 'x';}, any>
92+
>x : "x"
93+
94+
const ret = { x: 'x' };
95+
>ret : { x: string; }
96+
>{ x: 'x' } : { x: string; }
97+
>x : string
98+
>'x' : "x"
99+
100+
return Promise.resolve(ret); // Error
101+
>Promise.resolve(ret) : Promise<{ x: string; }>
102+
>Promise.resolve : { (): Promise<void>; <T>(value: T): Promise<Awaited<T>>; <T>(value: T | PromiseLike<T>): Promise<Awaited<T>>; }
103+
>Promise : PromiseConstructor
104+
>resolve : { (): Promise<void>; <T>(value: T): Promise<Awaited<T>>; <T>(value: T | PromiseLike<T>): Promise<Awaited<T>>; }
105+
>ret : { x: string; }
106+
}
107+
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+
}
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+
}

‎tests/cases/conformance/generators/generatorReturnContextualType.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,32 @@ function* f1(): Generator<any, { x: 'x' }, any> {
77
return { x: 'x' };
88
}
99

10+
function* g1(): Iterator<any, { x: 'x' }, any> {
11+
return { x: 'x' };
12+
}
13+
1014
async function* f2(): AsyncGenerator<any, { x: 'x' }, any> {
1115
return { x: 'x' };
1216
}
1317

18+
async function* g2(): AsyncIterator<any, { x: 'x' }, any> {
19+
return { x: 'x' };
20+
}
21+
1422
async function* f3(): AsyncGenerator<any, { x: 'x' }, any> {
1523
return Promise.resolve({ x: 'x' });
1624
}
1725

26+
async function* g3(): AsyncIterator<any, { x: 'x' }, any> {
27+
return Promise.resolve({ x: 'x' });
28+
}
29+
1830
async function* f4(): AsyncGenerator<any, { x: 'x' }, any> {
1931
const ret = { x: 'x' };
2032
return Promise.resolve(ret); // Error
2133
}
34+
35+
async function* g4(): AsyncIterator<any, { x: 'x' }, any> {
36+
const ret = { x: 'x' };
37+
return Promise.resolve(ret); // Error
38+
}

0 commit comments

Comments
 (0)
Please sign in to comment.