Skip to content

Commit 156d7a8

Browse files
committed
fix contextual return type in generator funcs
1 parent 5f4e6fb commit 156d7a8

File tree

6 files changed

+185
-17
lines changed

6 files changed

+185
-17
lines changed

src/compiler/checker.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26638,12 +26638,11 @@ namespace ts {
2663826638
if (contextualReturnType) {
2663926639
const functionFlags = getFunctionFlags(func);
2664026640
if (functionFlags & FunctionFlags.Generator) { // Generator or AsyncGenerator function
26641-
const use = functionFlags & FunctionFlags.Async ? IterationUse.AsyncGeneratorReturnType : IterationUse.GeneratorReturnType;
26642-
const iterationTypes = getIterationTypesOfIterable(contextualReturnType, use, /*errorNode*/ undefined);
26643-
if (!iterationTypes) {
26641+
const iterationReturnType = getIterationTypeOfGeneratorFunctionReturnType(IterationTypeKind.Return, contextualReturnType, (functionFlags & FunctionFlags.Async) !== 0);
26642+
if (!iterationReturnType) {
2664426643
return undefined;
2664526644
}
26646-
contextualReturnType = iterationTypes.returnType;
26645+
contextualReturnType = iterationReturnType;
2664726646
// falls through to unwrap Promise for AsyncGenerators
2664826647
}
2664926648

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, --, --))
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, --, --))
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, --, --))
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, --, --))
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, --, --))
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, --, --))
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, --, --))
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, --, --))
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 | PromiseLike<T>): Promise<T>; }
65+
>Promise : PromiseConstructor
66+
>resolve : { (): Promise<void>; <T>(value: T | PromiseLike<T>): Promise<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 | PromiseLike<T>): Promise<T>; }
103+
>Promise : PromiseConstructor
104+
>resolve : { (): Promise<void>; <T>(value: T | PromiseLike<T>): Promise<T>; }
105+
>ret : { x: string; }
106+
}
107+

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)