Skip to content

Commit 7119e2b

Browse files
authored
The iteration type of overloaded iterator signatures derives from the intersection of their return types (#39722)
1 parent faf128d commit 7119e2b

File tree

5 files changed

+85
-2
lines changed

5 files changed

+85
-2
lines changed

src/compiler/checker.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33624,7 +33624,7 @@ namespace ts {
3362433624
return setCachedIterationTypes(type, resolver.iterableCacheKey, noIterationTypes);
3362533625
}
3362633626

33627-
const iteratorType = getUnionType(map(signatures, getReturnTypeOfSignature), UnionReduction.Subtype);
33627+
const iteratorType = getIntersectionType(map(signatures, getReturnTypeOfSignature));
3362833628
const iterationTypes = getIterationTypesOfIterator(iteratorType, resolver, errorNode) ?? noIterationTypes;
3362933629
return setCachedIterationTypes(type, resolver.iterableCacheKey, iterationTypes);
3363033630
}
@@ -33830,7 +33830,7 @@ namespace ts {
3383033830

3383133831
// Resolve the *yield* and *return* types from the return type of the method (i.e. `IteratorResult`)
3383233832
let yieldType: Type;
33833-
const methodReturnType = methodReturnTypes ? getUnionType(methodReturnTypes, UnionReduction.Subtype) : neverType;
33833+
const methodReturnType = methodReturnTypes ? getIntersectionType(methodReturnTypes) : neverType;
3383433834
const resolvedMethodReturnType = resolver.resolveIterationType(methodReturnType, errorNode) || anyType;
3383533835
const iterationTypes = getIterationTypesOfIteratorResult(resolvedMethodReturnType);
3383633836
if (iterationTypes === noIterationTypes) {

tests/baselines/reference/for-of58.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
//// [for-of58.ts]
2+
type X = { x: 'x' };
3+
type Y = { y: 'y' };
4+
5+
declare const arr: X[] & Y[];
6+
7+
for (const item of arr) {
8+
item.x;
9+
item.y;
10+
}
11+
12+
13+
//// [for-of58.js]
14+
for (const item of arr) {
15+
item.x;
16+
item.y;
17+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
=== tests/cases/conformance/es6/for-ofStatements/for-of58.ts ===
2+
type X = { x: 'x' };
3+
>X : Symbol(X, Decl(for-of58.ts, 0, 0))
4+
>x : Symbol(x, Decl(for-of58.ts, 0, 10))
5+
6+
type Y = { y: 'y' };
7+
>Y : Symbol(Y, Decl(for-of58.ts, 0, 20))
8+
>y : Symbol(y, Decl(for-of58.ts, 1, 10))
9+
10+
declare const arr: X[] & Y[];
11+
>arr : Symbol(arr, Decl(for-of58.ts, 3, 13))
12+
>X : Symbol(X, Decl(for-of58.ts, 0, 0))
13+
>Y : Symbol(Y, Decl(for-of58.ts, 0, 20))
14+
15+
for (const item of arr) {
16+
>item : Symbol(item, Decl(for-of58.ts, 5, 10))
17+
>arr : Symbol(arr, Decl(for-of58.ts, 3, 13))
18+
19+
item.x;
20+
>item.x : Symbol(x, Decl(for-of58.ts, 0, 10))
21+
>item : Symbol(item, Decl(for-of58.ts, 5, 10))
22+
>x : Symbol(x, Decl(for-of58.ts, 0, 10))
23+
24+
item.y;
25+
>item.y : Symbol(y, Decl(for-of58.ts, 1, 10))
26+
>item : Symbol(item, Decl(for-of58.ts, 5, 10))
27+
>y : Symbol(y, Decl(for-of58.ts, 1, 10))
28+
}
29+
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
=== tests/cases/conformance/es6/for-ofStatements/for-of58.ts ===
2+
type X = { x: 'x' };
3+
>X : X
4+
>x : "x"
5+
6+
type Y = { y: 'y' };
7+
>Y : Y
8+
>y : "y"
9+
10+
declare const arr: X[] & Y[];
11+
>arr : X[] & Y[]
12+
13+
for (const item of arr) {
14+
>item : X & Y
15+
>arr : X[] & Y[]
16+
17+
item.x;
18+
>item.x : "x"
19+
>item : X & Y
20+
>x : "x"
21+
22+
item.y;
23+
>item.y : "y"
24+
>item : X & Y
25+
>y : "y"
26+
}
27+
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// @target: es6
2+
type X = { x: 'x' };
3+
type Y = { y: 'y' };
4+
5+
declare const arr: X[] & Y[];
6+
7+
for (const item of arr) {
8+
item.x;
9+
item.y;
10+
}

0 commit comments

Comments
 (0)