Skip to content

Commit ab3184b

Browse files
committed
Add tests
1 parent 97095c1 commit ab3184b

4 files changed

+490
-0
lines changed
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
mappedTypeIndexedAccessConstraint.ts(8,5): error TS18048: 'm1' is possibly 'undefined'.
2+
mappedTypeIndexedAccessConstraint.ts(10,5): error TS18048: 'm2' is possibly 'undefined'.
3+
mappedTypeIndexedAccessConstraint.ts(23,66): error TS2532: Object is possibly 'undefined'.
4+
mappedTypeIndexedAccessConstraint.ts(47,34): error TS2722: Cannot invoke an object which is possibly 'undefined'.
5+
6+
7+
==== mappedTypeIndexedAccessConstraint.ts (4 errors) ====
8+
type M0 = { a: 1, b: 2 };
9+
10+
type M1 = { [K in keyof Partial<M0>]: M0[K] };
11+
12+
type M2 = { [K in keyof Required<M1>]: M1[K] };
13+
14+
function foo<K extends keyof M0>(m1: M1[K], m2: M2[K]) {
15+
m1.toString(); // Error
16+
~~
17+
!!! error TS18048: 'm1' is possibly 'undefined'.
18+
m1?.toString();
19+
m2.toString(); // Error
20+
~~
21+
!!! error TS18048: 'm2' is possibly 'undefined'.
22+
m2?.toString();
23+
}
24+
25+
// Repro from #57487
26+
27+
type Obj = {
28+
a: 1,
29+
b: 2
30+
};
31+
32+
const mapped: { [K in keyof Partial<Obj>]: Obj[K] } = {};
33+
34+
const resolveMapped = <K extends keyof typeof mapped>(key: K) => mapped[key].toString(); // Error
35+
~~~~~~~~~~~
36+
!!! error TS2532: Object is possibly 'undefined'.
37+
38+
// Additional repro from #57487
39+
40+
const arr = ["foo", "12", 42] as const;
41+
42+
type Mappings = { foo: boolean, "12": number, 42: string };
43+
44+
type MapperArgs<K extends (typeof arr)[number]> = {
45+
v: K,
46+
i: number
47+
};
48+
49+
type SetOptional<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
50+
51+
type PartMappings = SetOptional<Mappings, "foo">;
52+
53+
const mapper: { [K in keyof PartMappings]: (o: MapperArgs<K>) => PartMappings[K] } = {
54+
foo: ({ v, i }) => v.length + i > 4,
55+
"12": ({ v, i }) => Number(v) + i,
56+
42: ({ v, i }) => `${v}${i}`,
57+
}
58+
59+
const resolveMapper1 = <K extends keyof typeof mapper>(
60+
key: K, o: MapperArgs<K>) => mapper[key](o); // Error
61+
~~~~~~~~~~~
62+
!!! error TS2722: Cannot invoke an object which is possibly 'undefined'.
63+
64+
const resolveMapper2 = <K extends keyof typeof mapper>(
65+
key: K, o: MapperArgs<K>) => mapper[key]?.(o)
66+
Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
//// [tests/cases/compiler/mappedTypeIndexedAccessConstraint.ts] ////
2+
3+
=== mappedTypeIndexedAccessConstraint.ts ===
4+
type M0 = { a: 1, b: 2 };
5+
>M0 : Symbol(M0, Decl(mappedTypeIndexedAccessConstraint.ts, 0, 0))
6+
>a : Symbol(a, Decl(mappedTypeIndexedAccessConstraint.ts, 0, 11))
7+
>b : Symbol(b, Decl(mappedTypeIndexedAccessConstraint.ts, 0, 17))
8+
9+
type M1 = { [K in keyof Partial<M0>]: M0[K] };
10+
>M1 : Symbol(M1, Decl(mappedTypeIndexedAccessConstraint.ts, 0, 25))
11+
>K : Symbol(K, Decl(mappedTypeIndexedAccessConstraint.ts, 2, 13))
12+
>Partial : Symbol(Partial, Decl(lib.es5.d.ts, --, --))
13+
>M0 : Symbol(M0, Decl(mappedTypeIndexedAccessConstraint.ts, 0, 0))
14+
>M0 : Symbol(M0, Decl(mappedTypeIndexedAccessConstraint.ts, 0, 0))
15+
>K : Symbol(K, Decl(mappedTypeIndexedAccessConstraint.ts, 2, 13))
16+
17+
type M2 = { [K in keyof Required<M1>]: M1[K] };
18+
>M2 : Symbol(M2, Decl(mappedTypeIndexedAccessConstraint.ts, 2, 46))
19+
>K : Symbol(K, Decl(mappedTypeIndexedAccessConstraint.ts, 4, 13))
20+
>Required : Symbol(Required, Decl(lib.es5.d.ts, --, --))
21+
>M1 : Symbol(M1, Decl(mappedTypeIndexedAccessConstraint.ts, 0, 25))
22+
>M1 : Symbol(M1, Decl(mappedTypeIndexedAccessConstraint.ts, 0, 25))
23+
>K : Symbol(K, Decl(mappedTypeIndexedAccessConstraint.ts, 4, 13))
24+
25+
function foo<K extends keyof M0>(m1: M1[K], m2: M2[K]) {
26+
>foo : Symbol(foo, Decl(mappedTypeIndexedAccessConstraint.ts, 4, 47))
27+
>K : Symbol(K, Decl(mappedTypeIndexedAccessConstraint.ts, 6, 13))
28+
>M0 : Symbol(M0, Decl(mappedTypeIndexedAccessConstraint.ts, 0, 0))
29+
>m1 : Symbol(m1, Decl(mappedTypeIndexedAccessConstraint.ts, 6, 33))
30+
>M1 : Symbol(M1, Decl(mappedTypeIndexedAccessConstraint.ts, 0, 25))
31+
>K : Symbol(K, Decl(mappedTypeIndexedAccessConstraint.ts, 6, 13))
32+
>m2 : Symbol(m2, Decl(mappedTypeIndexedAccessConstraint.ts, 6, 43))
33+
>M2 : Symbol(M2, Decl(mappedTypeIndexedAccessConstraint.ts, 2, 46))
34+
>K : Symbol(K, Decl(mappedTypeIndexedAccessConstraint.ts, 6, 13))
35+
36+
m1.toString(); // Error
37+
>m1.toString : Symbol(Number.toString, Decl(lib.es5.d.ts, --, --))
38+
>m1 : Symbol(m1, Decl(mappedTypeIndexedAccessConstraint.ts, 6, 33))
39+
>toString : Symbol(Number.toString, Decl(lib.es5.d.ts, --, --))
40+
41+
m1?.toString();
42+
>m1?.toString : Symbol(Number.toString, Decl(lib.es5.d.ts, --, --))
43+
>m1 : Symbol(m1, Decl(mappedTypeIndexedAccessConstraint.ts, 6, 33))
44+
>toString : Symbol(Number.toString, Decl(lib.es5.d.ts, --, --))
45+
46+
m2.toString(); // Error
47+
>m2.toString : Symbol(Number.toString, Decl(lib.es5.d.ts, --, --))
48+
>m2 : Symbol(m2, Decl(mappedTypeIndexedAccessConstraint.ts, 6, 43))
49+
>toString : Symbol(Number.toString, Decl(lib.es5.d.ts, --, --))
50+
51+
m2?.toString();
52+
>m2?.toString : Symbol(Number.toString, Decl(lib.es5.d.ts, --, --))
53+
>m2 : Symbol(m2, Decl(mappedTypeIndexedAccessConstraint.ts, 6, 43))
54+
>toString : Symbol(Number.toString, Decl(lib.es5.d.ts, --, --))
55+
}
56+
57+
// Repro from #57487
58+
59+
type Obj = {
60+
>Obj : Symbol(Obj, Decl(mappedTypeIndexedAccessConstraint.ts, 11, 1))
61+
62+
a: 1,
63+
>a : Symbol(a, Decl(mappedTypeIndexedAccessConstraint.ts, 15, 12))
64+
65+
b: 2
66+
>b : Symbol(b, Decl(mappedTypeIndexedAccessConstraint.ts, 16, 9))
67+
68+
};
69+
70+
const mapped: { [K in keyof Partial<Obj>]: Obj[K] } = {};
71+
>mapped : Symbol(mapped, Decl(mappedTypeIndexedAccessConstraint.ts, 20, 5))
72+
>K : Symbol(K, Decl(mappedTypeIndexedAccessConstraint.ts, 20, 17))
73+
>Partial : Symbol(Partial, Decl(lib.es5.d.ts, --, --))
74+
>Obj : Symbol(Obj, Decl(mappedTypeIndexedAccessConstraint.ts, 11, 1))
75+
>Obj : Symbol(Obj, Decl(mappedTypeIndexedAccessConstraint.ts, 11, 1))
76+
>K : Symbol(K, Decl(mappedTypeIndexedAccessConstraint.ts, 20, 17))
77+
78+
const resolveMapped = <K extends keyof typeof mapped>(key: K) => mapped[key].toString(); // Error
79+
>resolveMapped : Symbol(resolveMapped, Decl(mappedTypeIndexedAccessConstraint.ts, 22, 5))
80+
>K : Symbol(K, Decl(mappedTypeIndexedAccessConstraint.ts, 22, 23))
81+
>mapped : Symbol(mapped, Decl(mappedTypeIndexedAccessConstraint.ts, 20, 5))
82+
>key : Symbol(key, Decl(mappedTypeIndexedAccessConstraint.ts, 22, 54))
83+
>K : Symbol(K, Decl(mappedTypeIndexedAccessConstraint.ts, 22, 23))
84+
>mapped[key].toString : Symbol(Number.toString, Decl(lib.es5.d.ts, --, --))
85+
>mapped : Symbol(mapped, Decl(mappedTypeIndexedAccessConstraint.ts, 20, 5))
86+
>key : Symbol(key, Decl(mappedTypeIndexedAccessConstraint.ts, 22, 54))
87+
>toString : Symbol(Number.toString, Decl(lib.es5.d.ts, --, --))
88+
89+
// Additional repro from #57487
90+
91+
const arr = ["foo", "12", 42] as const;
92+
>arr : Symbol(arr, Decl(mappedTypeIndexedAccessConstraint.ts, 26, 5))
93+
>const : Symbol(const)
94+
95+
type Mappings = { foo: boolean, "12": number, 42: string };
96+
>Mappings : Symbol(Mappings, Decl(mappedTypeIndexedAccessConstraint.ts, 26, 39))
97+
>foo : Symbol(foo, Decl(mappedTypeIndexedAccessConstraint.ts, 28, 17))
98+
>"12" : Symbol("12", Decl(mappedTypeIndexedAccessConstraint.ts, 28, 31))
99+
>42 : Symbol(42, Decl(mappedTypeIndexedAccessConstraint.ts, 28, 45))
100+
101+
type MapperArgs<K extends (typeof arr)[number]> = {
102+
>MapperArgs : Symbol(MapperArgs, Decl(mappedTypeIndexedAccessConstraint.ts, 28, 59))
103+
>K : Symbol(K, Decl(mappedTypeIndexedAccessConstraint.ts, 30, 16))
104+
>arr : Symbol(arr, Decl(mappedTypeIndexedAccessConstraint.ts, 26, 5))
105+
106+
v: K,
107+
>v : Symbol(v, Decl(mappedTypeIndexedAccessConstraint.ts, 30, 51))
108+
>K : Symbol(K, Decl(mappedTypeIndexedAccessConstraint.ts, 30, 16))
109+
110+
i: number
111+
>i : Symbol(i, Decl(mappedTypeIndexedAccessConstraint.ts, 31, 9))
112+
113+
};
114+
115+
type SetOptional<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
116+
>SetOptional : Symbol(SetOptional, Decl(mappedTypeIndexedAccessConstraint.ts, 33, 2))
117+
>T : Symbol(T, Decl(mappedTypeIndexedAccessConstraint.ts, 35, 17))
118+
>K : Symbol(K, Decl(mappedTypeIndexedAccessConstraint.ts, 35, 19))
119+
>T : Symbol(T, Decl(mappedTypeIndexedAccessConstraint.ts, 35, 17))
120+
>Omit : Symbol(Omit, Decl(lib.es5.d.ts, --, --))
121+
>T : Symbol(T, Decl(mappedTypeIndexedAccessConstraint.ts, 35, 17))
122+
>K : Symbol(K, Decl(mappedTypeIndexedAccessConstraint.ts, 35, 19))
123+
>Partial : Symbol(Partial, Decl(lib.es5.d.ts, --, --))
124+
>Pick : Symbol(Pick, Decl(lib.es5.d.ts, --, --))
125+
>T : Symbol(T, Decl(mappedTypeIndexedAccessConstraint.ts, 35, 17))
126+
>K : Symbol(K, Decl(mappedTypeIndexedAccessConstraint.ts, 35, 19))
127+
128+
type PartMappings = SetOptional<Mappings, "foo">;
129+
>PartMappings : Symbol(PartMappings, Decl(mappedTypeIndexedAccessConstraint.ts, 35, 74))
130+
>SetOptional : Symbol(SetOptional, Decl(mappedTypeIndexedAccessConstraint.ts, 33, 2))
131+
>Mappings : Symbol(Mappings, Decl(mappedTypeIndexedAccessConstraint.ts, 26, 39))
132+
133+
const mapper: { [K in keyof PartMappings]: (o: MapperArgs<K>) => PartMappings[K] } = {
134+
>mapper : Symbol(mapper, Decl(mappedTypeIndexedAccessConstraint.ts, 39, 5))
135+
>K : Symbol(K, Decl(mappedTypeIndexedAccessConstraint.ts, 39, 17))
136+
>PartMappings : Symbol(PartMappings, Decl(mappedTypeIndexedAccessConstraint.ts, 35, 74))
137+
>o : Symbol(o, Decl(mappedTypeIndexedAccessConstraint.ts, 39, 44))
138+
>MapperArgs : Symbol(MapperArgs, Decl(mappedTypeIndexedAccessConstraint.ts, 28, 59))
139+
>K : Symbol(K, Decl(mappedTypeIndexedAccessConstraint.ts, 39, 17))
140+
>PartMappings : Symbol(PartMappings, Decl(mappedTypeIndexedAccessConstraint.ts, 35, 74))
141+
>K : Symbol(K, Decl(mappedTypeIndexedAccessConstraint.ts, 39, 17))
142+
143+
foo: ({ v, i }) => v.length + i > 4,
144+
>foo : Symbol(foo, Decl(mappedTypeIndexedAccessConstraint.ts, 39, 86))
145+
>v : Symbol(v, Decl(mappedTypeIndexedAccessConstraint.ts, 40, 11))
146+
>i : Symbol(i, Decl(mappedTypeIndexedAccessConstraint.ts, 40, 14))
147+
>v.length : Symbol(String.length, Decl(lib.es5.d.ts, --, --))
148+
>v : Symbol(v, Decl(mappedTypeIndexedAccessConstraint.ts, 40, 11))
149+
>length : Symbol(String.length, Decl(lib.es5.d.ts, --, --))
150+
>i : Symbol(i, Decl(mappedTypeIndexedAccessConstraint.ts, 40, 14))
151+
152+
"12": ({ v, i }) => Number(v) + i,
153+
>"12" : Symbol("12", Decl(mappedTypeIndexedAccessConstraint.ts, 40, 40))
154+
>v : Symbol(v, Decl(mappedTypeIndexedAccessConstraint.ts, 41, 12))
155+
>i : Symbol(i, Decl(mappedTypeIndexedAccessConstraint.ts, 41, 15))
156+
>Number : Symbol(Number, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
157+
>v : Symbol(v, Decl(mappedTypeIndexedAccessConstraint.ts, 41, 12))
158+
>i : Symbol(i, Decl(mappedTypeIndexedAccessConstraint.ts, 41, 15))
159+
160+
42: ({ v, i }) => `${v}${i}`,
161+
>42 : Symbol(42, Decl(mappedTypeIndexedAccessConstraint.ts, 41, 38))
162+
>v : Symbol(v, Decl(mappedTypeIndexedAccessConstraint.ts, 42, 10))
163+
>i : Symbol(i, Decl(mappedTypeIndexedAccessConstraint.ts, 42, 13))
164+
>v : Symbol(v, Decl(mappedTypeIndexedAccessConstraint.ts, 42, 10))
165+
>i : Symbol(i, Decl(mappedTypeIndexedAccessConstraint.ts, 42, 13))
166+
}
167+
168+
const resolveMapper1 = <K extends keyof typeof mapper>(
169+
>resolveMapper1 : Symbol(resolveMapper1, Decl(mappedTypeIndexedAccessConstraint.ts, 45, 5))
170+
>K : Symbol(K, Decl(mappedTypeIndexedAccessConstraint.ts, 45, 24))
171+
>mapper : Symbol(mapper, Decl(mappedTypeIndexedAccessConstraint.ts, 39, 5))
172+
173+
key: K, o: MapperArgs<K>) => mapper[key](o); // Error
174+
>key : Symbol(key, Decl(mappedTypeIndexedAccessConstraint.ts, 45, 55))
175+
>K : Symbol(K, Decl(mappedTypeIndexedAccessConstraint.ts, 45, 24))
176+
>o : Symbol(o, Decl(mappedTypeIndexedAccessConstraint.ts, 46, 11))
177+
>MapperArgs : Symbol(MapperArgs, Decl(mappedTypeIndexedAccessConstraint.ts, 28, 59))
178+
>K : Symbol(K, Decl(mappedTypeIndexedAccessConstraint.ts, 45, 24))
179+
>mapper : Symbol(mapper, Decl(mappedTypeIndexedAccessConstraint.ts, 39, 5))
180+
>key : Symbol(key, Decl(mappedTypeIndexedAccessConstraint.ts, 45, 55))
181+
>o : Symbol(o, Decl(mappedTypeIndexedAccessConstraint.ts, 46, 11))
182+
183+
const resolveMapper2 = <K extends keyof typeof mapper>(
184+
>resolveMapper2 : Symbol(resolveMapper2, Decl(mappedTypeIndexedAccessConstraint.ts, 48, 5))
185+
>K : Symbol(K, Decl(mappedTypeIndexedAccessConstraint.ts, 48, 24))
186+
>mapper : Symbol(mapper, Decl(mappedTypeIndexedAccessConstraint.ts, 39, 5))
187+
188+
key: K, o: MapperArgs<K>) => mapper[key]?.(o)
189+
>key : Symbol(key, Decl(mappedTypeIndexedAccessConstraint.ts, 48, 55))
190+
>K : Symbol(K, Decl(mappedTypeIndexedAccessConstraint.ts, 48, 24))
191+
>o : Symbol(o, Decl(mappedTypeIndexedAccessConstraint.ts, 49, 11))
192+
>MapperArgs : Symbol(MapperArgs, Decl(mappedTypeIndexedAccessConstraint.ts, 28, 59))
193+
>K : Symbol(K, Decl(mappedTypeIndexedAccessConstraint.ts, 48, 24))
194+
>mapper : Symbol(mapper, Decl(mappedTypeIndexedAccessConstraint.ts, 39, 5))
195+
>key : Symbol(key, Decl(mappedTypeIndexedAccessConstraint.ts, 48, 55))
196+
>o : Symbol(o, Decl(mappedTypeIndexedAccessConstraint.ts, 49, 11))
197+

0 commit comments

Comments
 (0)