Skip to content

Commit 56aa3d5

Browse files
authored
Normalize generic tuple types with Simplifiable elements (#52385)
1 parent a5e6dee commit 56aa3d5

File tree

4 files changed

+107
-0
lines changed

4 files changed

+107
-0
lines changed

src/compiler/checker.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20126,6 +20126,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
2012620126
function getNormalizedType(type: Type, writing: boolean): Type {
2012720127
while (true) {
2012820128
const t = isFreshLiteralType(type) ? (type as FreshableType).regularType :
20129+
isGenericTupleType(type) ? getNormalizedTupleType(type, writing) :
2012920130
getObjectFlags(type) & ObjectFlags.Reference ? (type as TypeReference).node ? createTypeReference((type as TypeReference).target, getTypeArguments(type as TypeReference)) : getSingleBaseForNonAugmentingSubtype(type) || type :
2013020131
type.flags & TypeFlags.UnionOrIntersection ? getNormalizedUnionOrIntersectionType(type as UnionOrIntersectionType, writing) :
2013120132
type.flags & TypeFlags.Substitution ? writing ? (type as SubstitutionType).baseType : getSubstitutionIntersection(type as SubstitutionType) :
@@ -20150,6 +20151,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
2015020151
return type;
2015120152
}
2015220153

20154+
function getNormalizedTupleType(type: TupleTypeReference, writing: boolean): Type {
20155+
const elements = getTypeArguments(type);
20156+
const normalizedElements = sameMap(elements, t => t.flags & TypeFlags.Simplifiable ? getSimplifiedType(t, writing) : t);
20157+
return elements !== normalizedElements ? createNormalizedTupleType(type.target, normalizedElements) : type;
20158+
}
20159+
2015320160
/**
2015420161
* Checks if 'source' is related to 'target' (e.g.: is a assignable to).
2015520162
* @param source The left-hand-side of the relation.
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
=== tests/cases/compiler/genericTupleWithSimplifiableElements.ts ===
2+
// repro from #52354
3+
4+
type SS1 = string;
5+
>SS1 : Symbol(SS1, Decl(genericTupleWithSimplifiableElements.ts, 0, 0))
6+
7+
let y: [t: "AAA", ...args: { [S in SS1]: [a: number]; }[SS1]] = ["AAA", 1];
8+
>y : Symbol(y, Decl(genericTupleWithSimplifiableElements.ts, 3, 3))
9+
>S : Symbol(S, Decl(genericTupleWithSimplifiableElements.ts, 3, 30))
10+
>SS1 : Symbol(SS1, Decl(genericTupleWithSimplifiableElements.ts, 0, 0))
11+
>SS1 : Symbol(SS1, Decl(genericTupleWithSimplifiableElements.ts, 0, 0))
12+
13+
type SS2 = "1" | "2" | "3";
14+
>SS2 : Symbol(SS2, Decl(genericTupleWithSimplifiableElements.ts, 3, 75))
15+
16+
let z: [t: "AAA", ...args: { [S in SS2]: [a: number]; }[SS2]] = ["AAA", 1];
17+
>z : Symbol(z, Decl(genericTupleWithSimplifiableElements.ts, 6, 3))
18+
>S : Symbol(S, Decl(genericTupleWithSimplifiableElements.ts, 6, 30))
19+
>SS2 : Symbol(SS2, Decl(genericTupleWithSimplifiableElements.ts, 3, 75))
20+
>SS2 : Symbol(SS2, Decl(genericTupleWithSimplifiableElements.ts, 3, 75))
21+
22+
class I<SS extends string>{
23+
>I : Symbol(I, Decl(genericTupleWithSimplifiableElements.ts, 6, 75))
24+
>SS : Symbol(SS, Decl(genericTupleWithSimplifiableElements.ts, 8, 8))
25+
26+
f() {
27+
>f : Symbol(I.f, Decl(genericTupleWithSimplifiableElements.ts, 8, 27))
28+
29+
let w: [...args: { [S in SS]: [a: number]; }[SS]] = [1];
30+
>w : Symbol(w, Decl(genericTupleWithSimplifiableElements.ts, 10, 11))
31+
>S : Symbol(S, Decl(genericTupleWithSimplifiableElements.ts, 10, 28))
32+
>SS : Symbol(SS, Decl(genericTupleWithSimplifiableElements.ts, 8, 8))
33+
>SS : Symbol(SS, Decl(genericTupleWithSimplifiableElements.ts, 8, 8))
34+
35+
let x: [t: "AAA", ...args: { [S in SS]: [a: number]; }[SS]] = ["AAA", 1];
36+
>x : Symbol(x, Decl(genericTupleWithSimplifiableElements.ts, 12, 11))
37+
>S : Symbol(S, Decl(genericTupleWithSimplifiableElements.ts, 12, 38))
38+
>SS : Symbol(SS, Decl(genericTupleWithSimplifiableElements.ts, 8, 8))
39+
>SS : Symbol(SS, Decl(genericTupleWithSimplifiableElements.ts, 8, 8))
40+
}
41+
}
42+
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
=== tests/cases/compiler/genericTupleWithSimplifiableElements.ts ===
2+
// repro from #52354
3+
4+
type SS1 = string;
5+
>SS1 : string
6+
7+
let y: [t: "AAA", ...args: { [S in SS1]: [a: number]; }[SS1]] = ["AAA", 1];
8+
>y : [t: "AAA", a: number]
9+
>["AAA", 1] : ["AAA", number]
10+
>"AAA" : "AAA"
11+
>1 : 1
12+
13+
type SS2 = "1" | "2" | "3";
14+
>SS2 : "1" | "2" | "3"
15+
16+
let z: [t: "AAA", ...args: { [S in SS2]: [a: number]; }[SS2]] = ["AAA", 1];
17+
>z : [t: "AAA", a: number]
18+
>["AAA", 1] : ["AAA", number]
19+
>"AAA" : "AAA"
20+
>1 : 1
21+
22+
class I<SS extends string>{
23+
>I : I<SS>
24+
25+
f() {
26+
>f : () => void
27+
28+
let w: [...args: { [S in SS]: [a: number]; }[SS]] = [1];
29+
>w : [...args: { [S in SS]: [a: number]; }[SS]]
30+
>[1] : [1]
31+
>1 : 1
32+
33+
let x: [t: "AAA", ...args: { [S in SS]: [a: number]; }[SS]] = ["AAA", 1];
34+
>x : [t: "AAA", ...args: { [S in SS]: [a: number]; }[SS]]
35+
>["AAA", 1] : ["AAA", 1]
36+
>"AAA" : "AAA"
37+
>1 : 1
38+
}
39+
}
40+
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// @strict: true
2+
// @noEmit: true
3+
4+
// repro from #52354
5+
6+
type SS1 = string;
7+
let y: [t: "AAA", ...args: { [S in SS1]: [a: number]; }[SS1]] = ["AAA", 1];
8+
9+
type SS2 = "1" | "2" | "3";
10+
let z: [t: "AAA", ...args: { [S in SS2]: [a: number]; }[SS2]] = ["AAA", 1];
11+
12+
class I<SS extends string>{
13+
f() {
14+
let w: [...args: { [S in SS]: [a: number]; }[SS]] = [1];
15+
16+
let x: [t: "AAA", ...args: { [S in SS]: [a: number]; }[SS]] = ["AAA", 1];
17+
}
18+
}

0 commit comments

Comments
 (0)