Skip to content

Commit c5b8f4f

Browse files
authored
Fix relation between generic mapped types and types with index signatures (#38761)
* Fix relation between generic mapped type and type with index signature(s) * Add tests
1 parent ba357e4 commit c5b8f4f

File tree

5 files changed

+241
-3
lines changed

5 files changed

+241
-3
lines changed

src/compiler/checker.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17288,9 +17288,10 @@ namespace ts {
1728817288
return Ternary.True;
1728917289
}
1729017290
if (isGenericMappedType(source)) {
17291-
// A generic mapped type { [P in K]: T } is related to an index signature { [x: string]: U }
17292-
// if T is related to U.
17293-
return kind === IndexKind.String ? isRelatedTo(getTemplateTypeFromMappedType(source), targetType, reportErrors) : Ternary.False;
17291+
// A generic mapped type { [P in K]: T } is related to a type with an index signature
17292+
// { [x: string]: U }, and optionally with an index signature { [x: number]: V },
17293+
// if T is related to U and V.
17294+
return getIndexTypeOfType(target, IndexKind.String) ? isRelatedTo(getTemplateTypeFromMappedType(source), targetType, reportErrors) : Ternary.False;
1729417295
}
1729517296
const indexType = getIndexTypeOfType(source, kind) || kind === IndexKind.Number && getIndexTypeOfType(source, IndexKind.String);
1729617297
if (indexType) {
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
//// [mappedTypeAndIndexSignatureRelation.ts]
2+
type Same<T> = { [P in keyof T]: T[P] };
3+
4+
type T1<T extends Record<PropertyKey, number>> = T;
5+
type T2<U extends Record<PropertyKey, number>> = T1<Same<U>>;
6+
7+
// Repro from #38235
8+
9+
type Foo<IdentifierT extends Record<PropertyKey, PropertyKey>> =
10+
IdentifierT
11+
;
12+
13+
type Bar<IdentifierT extends Record<PropertyKey, PropertyKey>, T> =
14+
{
15+
[k in keyof T] : Foo<IdentifierT & { k : k }>
16+
}
17+
;
18+
19+
type Merge2<T> = { [k in keyof T] : T[k] }
20+
type Bar2<IdentifierT extends Record<PropertyKey, PropertyKey>, T> =
21+
{
22+
[k in keyof T]: Foo<Merge2<IdentifierT & { k: k }>>
23+
}
24+
;
25+
26+
type Identity<T> = T;
27+
type Merge3<T> = Identity<{ [k in keyof T] : T[k] }>
28+
type Bar3<IdentifierT extends Record<PropertyKey, PropertyKey>, T> =
29+
{
30+
[k in keyof T]: Foo<Merge3<IdentifierT & { k: k }>>
31+
}
32+
;
33+
34+
35+
//// [mappedTypeAndIndexSignatureRelation.js]
36+
"use strict";
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
=== tests/cases/compiler/mappedTypeAndIndexSignatureRelation.ts ===
2+
type Same<T> = { [P in keyof T]: T[P] };
3+
>Same : Symbol(Same, Decl(mappedTypeAndIndexSignatureRelation.ts, 0, 0))
4+
>T : Symbol(T, Decl(mappedTypeAndIndexSignatureRelation.ts, 0, 10))
5+
>P : Symbol(P, Decl(mappedTypeAndIndexSignatureRelation.ts, 0, 18))
6+
>T : Symbol(T, Decl(mappedTypeAndIndexSignatureRelation.ts, 0, 10))
7+
>T : Symbol(T, Decl(mappedTypeAndIndexSignatureRelation.ts, 0, 10))
8+
>P : Symbol(P, Decl(mappedTypeAndIndexSignatureRelation.ts, 0, 18))
9+
10+
type T1<T extends Record<PropertyKey, number>> = T;
11+
>T1 : Symbol(T1, Decl(mappedTypeAndIndexSignatureRelation.ts, 0, 40))
12+
>T : Symbol(T, Decl(mappedTypeAndIndexSignatureRelation.ts, 2, 8))
13+
>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --))
14+
>PropertyKey : Symbol(PropertyKey, Decl(lib.es5.d.ts, --, --))
15+
>T : Symbol(T, Decl(mappedTypeAndIndexSignatureRelation.ts, 2, 8))
16+
17+
type T2<U extends Record<PropertyKey, number>> = T1<Same<U>>;
18+
>T2 : Symbol(T2, Decl(mappedTypeAndIndexSignatureRelation.ts, 2, 51))
19+
>U : Symbol(U, Decl(mappedTypeAndIndexSignatureRelation.ts, 3, 8))
20+
>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --))
21+
>PropertyKey : Symbol(PropertyKey, Decl(lib.es5.d.ts, --, --))
22+
>T1 : Symbol(T1, Decl(mappedTypeAndIndexSignatureRelation.ts, 0, 40))
23+
>Same : Symbol(Same, Decl(mappedTypeAndIndexSignatureRelation.ts, 0, 0))
24+
>U : Symbol(U, Decl(mappedTypeAndIndexSignatureRelation.ts, 3, 8))
25+
26+
// Repro from #38235
27+
28+
type Foo<IdentifierT extends Record<PropertyKey, PropertyKey>> =
29+
>Foo : Symbol(Foo, Decl(mappedTypeAndIndexSignatureRelation.ts, 3, 61))
30+
>IdentifierT : Symbol(IdentifierT, Decl(mappedTypeAndIndexSignatureRelation.ts, 7, 9))
31+
>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --))
32+
>PropertyKey : Symbol(PropertyKey, Decl(lib.es5.d.ts, --, --))
33+
>PropertyKey : Symbol(PropertyKey, Decl(lib.es5.d.ts, --, --))
34+
35+
IdentifierT
36+
>IdentifierT : Symbol(IdentifierT, Decl(mappedTypeAndIndexSignatureRelation.ts, 7, 9))
37+
38+
;
39+
40+
type Bar<IdentifierT extends Record<PropertyKey, PropertyKey>, T> =
41+
>Bar : Symbol(Bar, Decl(mappedTypeAndIndexSignatureRelation.ts, 9, 1))
42+
>IdentifierT : Symbol(IdentifierT, Decl(mappedTypeAndIndexSignatureRelation.ts, 11, 9))
43+
>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --))
44+
>PropertyKey : Symbol(PropertyKey, Decl(lib.es5.d.ts, --, --))
45+
>PropertyKey : Symbol(PropertyKey, Decl(lib.es5.d.ts, --, --))
46+
>T : Symbol(T, Decl(mappedTypeAndIndexSignatureRelation.ts, 11, 62))
47+
{
48+
[k in keyof T] : Foo<IdentifierT & { k : k }>
49+
>k : Symbol(k, Decl(mappedTypeAndIndexSignatureRelation.ts, 13, 9))
50+
>T : Symbol(T, Decl(mappedTypeAndIndexSignatureRelation.ts, 11, 62))
51+
>Foo : Symbol(Foo, Decl(mappedTypeAndIndexSignatureRelation.ts, 3, 61))
52+
>IdentifierT : Symbol(IdentifierT, Decl(mappedTypeAndIndexSignatureRelation.ts, 11, 9))
53+
>k : Symbol(k, Decl(mappedTypeAndIndexSignatureRelation.ts, 13, 44))
54+
>k : Symbol(k, Decl(mappedTypeAndIndexSignatureRelation.ts, 13, 9))
55+
}
56+
;
57+
58+
type Merge2<T> = { [k in keyof T] : T[k] }
59+
>Merge2 : Symbol(Merge2, Decl(mappedTypeAndIndexSignatureRelation.ts, 15, 1))
60+
>T : Symbol(T, Decl(mappedTypeAndIndexSignatureRelation.ts, 17, 12))
61+
>k : Symbol(k, Decl(mappedTypeAndIndexSignatureRelation.ts, 17, 20))
62+
>T : Symbol(T, Decl(mappedTypeAndIndexSignatureRelation.ts, 17, 12))
63+
>T : Symbol(T, Decl(mappedTypeAndIndexSignatureRelation.ts, 17, 12))
64+
>k : Symbol(k, Decl(mappedTypeAndIndexSignatureRelation.ts, 17, 20))
65+
66+
type Bar2<IdentifierT extends Record<PropertyKey, PropertyKey>, T> =
67+
>Bar2 : Symbol(Bar2, Decl(mappedTypeAndIndexSignatureRelation.ts, 17, 42))
68+
>IdentifierT : Symbol(IdentifierT, Decl(mappedTypeAndIndexSignatureRelation.ts, 18, 10))
69+
>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --))
70+
>PropertyKey : Symbol(PropertyKey, Decl(lib.es5.d.ts, --, --))
71+
>PropertyKey : Symbol(PropertyKey, Decl(lib.es5.d.ts, --, --))
72+
>T : Symbol(T, Decl(mappedTypeAndIndexSignatureRelation.ts, 18, 63))
73+
{
74+
[k in keyof T]: Foo<Merge2<IdentifierT & { k: k }>>
75+
>k : Symbol(k, Decl(mappedTypeAndIndexSignatureRelation.ts, 20, 9))
76+
>T : Symbol(T, Decl(mappedTypeAndIndexSignatureRelation.ts, 18, 63))
77+
>Foo : Symbol(Foo, Decl(mappedTypeAndIndexSignatureRelation.ts, 3, 61))
78+
>Merge2 : Symbol(Merge2, Decl(mappedTypeAndIndexSignatureRelation.ts, 15, 1))
79+
>IdentifierT : Symbol(IdentifierT, Decl(mappedTypeAndIndexSignatureRelation.ts, 18, 10))
80+
>k : Symbol(k, Decl(mappedTypeAndIndexSignatureRelation.ts, 20, 50))
81+
>k : Symbol(k, Decl(mappedTypeAndIndexSignatureRelation.ts, 20, 9))
82+
}
83+
;
84+
85+
type Identity<T> = T;
86+
>Identity : Symbol(Identity, Decl(mappedTypeAndIndexSignatureRelation.ts, 22, 1))
87+
>T : Symbol(T, Decl(mappedTypeAndIndexSignatureRelation.ts, 24, 14))
88+
>T : Symbol(T, Decl(mappedTypeAndIndexSignatureRelation.ts, 24, 14))
89+
90+
type Merge3<T> = Identity<{ [k in keyof T] : T[k] }>
91+
>Merge3 : Symbol(Merge3, Decl(mappedTypeAndIndexSignatureRelation.ts, 24, 21))
92+
>T : Symbol(T, Decl(mappedTypeAndIndexSignatureRelation.ts, 25, 12))
93+
>Identity : Symbol(Identity, Decl(mappedTypeAndIndexSignatureRelation.ts, 22, 1))
94+
>k : Symbol(k, Decl(mappedTypeAndIndexSignatureRelation.ts, 25, 29))
95+
>T : Symbol(T, Decl(mappedTypeAndIndexSignatureRelation.ts, 25, 12))
96+
>T : Symbol(T, Decl(mappedTypeAndIndexSignatureRelation.ts, 25, 12))
97+
>k : Symbol(k, Decl(mappedTypeAndIndexSignatureRelation.ts, 25, 29))
98+
99+
type Bar3<IdentifierT extends Record<PropertyKey, PropertyKey>, T> =
100+
>Bar3 : Symbol(Bar3, Decl(mappedTypeAndIndexSignatureRelation.ts, 25, 52))
101+
>IdentifierT : Symbol(IdentifierT, Decl(mappedTypeAndIndexSignatureRelation.ts, 26, 10))
102+
>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --))
103+
>PropertyKey : Symbol(PropertyKey, Decl(lib.es5.d.ts, --, --))
104+
>PropertyKey : Symbol(PropertyKey, Decl(lib.es5.d.ts, --, --))
105+
>T : Symbol(T, Decl(mappedTypeAndIndexSignatureRelation.ts, 26, 63))
106+
{
107+
[k in keyof T]: Foo<Merge3<IdentifierT & { k: k }>>
108+
>k : Symbol(k, Decl(mappedTypeAndIndexSignatureRelation.ts, 28, 9))
109+
>T : Symbol(T, Decl(mappedTypeAndIndexSignatureRelation.ts, 26, 63))
110+
>Foo : Symbol(Foo, Decl(mappedTypeAndIndexSignatureRelation.ts, 3, 61))
111+
>Merge3 : Symbol(Merge3, Decl(mappedTypeAndIndexSignatureRelation.ts, 24, 21))
112+
>IdentifierT : Symbol(IdentifierT, Decl(mappedTypeAndIndexSignatureRelation.ts, 26, 10))
113+
>k : Symbol(k, Decl(mappedTypeAndIndexSignatureRelation.ts, 28, 50))
114+
>k : Symbol(k, Decl(mappedTypeAndIndexSignatureRelation.ts, 28, 9))
115+
}
116+
;
117+
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
=== tests/cases/compiler/mappedTypeAndIndexSignatureRelation.ts ===
2+
type Same<T> = { [P in keyof T]: T[P] };
3+
>Same : Same<T>
4+
5+
type T1<T extends Record<PropertyKey, number>> = T;
6+
>T1 : T
7+
8+
type T2<U extends Record<PropertyKey, number>> = T1<Same<U>>;
9+
>T2 : Same<U>
10+
11+
// Repro from #38235
12+
13+
type Foo<IdentifierT extends Record<PropertyKey, PropertyKey>> =
14+
>Foo : IdentifierT
15+
16+
IdentifierT
17+
;
18+
19+
type Bar<IdentifierT extends Record<PropertyKey, PropertyKey>, T> =
20+
>Bar : Bar<IdentifierT, T>
21+
{
22+
[k in keyof T] : Foo<IdentifierT & { k : k }>
23+
>k : k
24+
}
25+
;
26+
27+
type Merge2<T> = { [k in keyof T] : T[k] }
28+
>Merge2 : Merge2<T>
29+
30+
type Bar2<IdentifierT extends Record<PropertyKey, PropertyKey>, T> =
31+
>Bar2 : Bar2<IdentifierT, T>
32+
{
33+
[k in keyof T]: Foo<Merge2<IdentifierT & { k: k }>>
34+
>k : k
35+
}
36+
;
37+
38+
type Identity<T> = T;
39+
>Identity : T
40+
41+
type Merge3<T> = Identity<{ [k in keyof T] : T[k] }>
42+
>Merge3 : { [k in keyof T]: T[k]; }
43+
44+
type Bar3<IdentifierT extends Record<PropertyKey, PropertyKey>, T> =
45+
>Bar3 : Bar3<IdentifierT, T>
46+
{
47+
[k in keyof T]: Foo<Merge3<IdentifierT & { k: k }>>
48+
>k : k
49+
}
50+
;
51+
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// @strict: true
2+
3+
type Same<T> = { [P in keyof T]: T[P] };
4+
5+
type T1<T extends Record<PropertyKey, number>> = T;
6+
type T2<U extends Record<PropertyKey, number>> = T1<Same<U>>;
7+
8+
// Repro from #38235
9+
10+
type Foo<IdentifierT extends Record<PropertyKey, PropertyKey>> =
11+
IdentifierT
12+
;
13+
14+
type Bar<IdentifierT extends Record<PropertyKey, PropertyKey>, T> =
15+
{
16+
[k in keyof T] : Foo<IdentifierT & { k : k }>
17+
}
18+
;
19+
20+
type Merge2<T> = { [k in keyof T] : T[k] }
21+
type Bar2<IdentifierT extends Record<PropertyKey, PropertyKey>, T> =
22+
{
23+
[k in keyof T]: Foo<Merge2<IdentifierT & { k: k }>>
24+
}
25+
;
26+
27+
type Identity<T> = T;
28+
type Merge3<T> = Identity<{ [k in keyof T] : T[k] }>
29+
type Bar3<IdentifierT extends Record<PropertyKey, PropertyKey>, T> =
30+
{
31+
[k in keyof T]: Foo<Merge3<IdentifierT & { k: k }>>
32+
}
33+
;

0 commit comments

Comments
 (0)