Skip to content

Commit 3ba5aa9

Browse files
authored
Add regression test for #29692 (#30325)
1 parent ca9566f commit 3ba5aa9

File tree

5 files changed

+507
-0
lines changed

5 files changed

+507
-0
lines changed
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
tests/cases/compiler/deepKeysIndexing.ts(53,22): error TS2345: Argument of type 'true' is not assignable to parameter of type '123'.
2+
tests/cases/compiler/deepKeysIndexing.ts(54,23): error TS2345: Argument of type 'true' is not assignable to parameter of type '123'.
3+
tests/cases/compiler/deepKeysIndexing.ts(55,26): error TS2345: Argument of type 'true' is not assignable to parameter of type '123'.
4+
5+
6+
==== tests/cases/compiler/deepKeysIndexing.ts (3 errors) ====
7+
// regression test from https://github.com/Microsoft/TypeScript/issues/29692
8+
interface DeepObject {
9+
[k1: string]: {
10+
[k2: string]: any;
11+
};
12+
}
13+
14+
type keys2broken<
15+
O extends DeepObject,
16+
K1 extends keyof O
17+
> = O[K1] extends object ? Extract<keyof O[K1], string> : never;
18+
19+
type keys2working<
20+
O extends DeepObject,
21+
K1 extends keyof O
22+
> = O[K1] extends object ? keyof O[K1] : never;
23+
24+
type keys2workaround<O extends DeepObject, K1 extends keyof O> = Extract<
25+
O[K1] extends object ? keyof O[K1] : never,
26+
string
27+
>;
28+
29+
interface Foo extends DeepObject {
30+
a: {
31+
"1": 123;
32+
"2": string;
33+
"3": boolean;
34+
};
35+
}
36+
37+
class Bar<O extends DeepObject> {
38+
broken<
39+
K1 extends keyof O,
40+
K2 extends keys2broken<O, K1>,
41+
V extends O[K1][K2]
42+
>(k1: K1, k2: K2, value: V) {}
43+
44+
working<
45+
K1 extends keyof O,
46+
K2 extends keys2working<O, K1>,
47+
V extends O[K1][K2]
48+
>(k1: K1, k2: K2, value: V) {}
49+
50+
workaround<
51+
K1 extends keyof O,
52+
K2 extends keys2workaround<O, K1>,
53+
V extends O[K1][K2]
54+
>(k1: K1, k2: K2, value: V) {}
55+
}
56+
57+
const bar = new Bar<Foo>();
58+
// all 3 of the below should error on passing `true` for `"1"`
59+
bar.broken("a", "1", true); // was broken in the past - with 2nd argument incorrectly of type "1" | "2" | "3".
60+
~~~~
61+
!!! error TS2345: Argument of type 'true' is not assignable to parameter of type '123'.
62+
bar.working("a", "1", true); // ok - true is not allowed
63+
~~~~
64+
!!! error TS2345: Argument of type 'true' is not assignable to parameter of type '123'.
65+
bar.workaround("a", "1", true); // ok - true is not allowed
66+
~~~~
67+
!!! error TS2345: Argument of type 'true' is not assignable to parameter of type '123'.
68+
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
//// [deepKeysIndexing.ts]
2+
// regression test from https://github.com/Microsoft/TypeScript/issues/29692
3+
interface DeepObject {
4+
[k1: string]: {
5+
[k2: string]: any;
6+
};
7+
}
8+
9+
type keys2broken<
10+
O extends DeepObject,
11+
K1 extends keyof O
12+
> = O[K1] extends object ? Extract<keyof O[K1], string> : never;
13+
14+
type keys2working<
15+
O extends DeepObject,
16+
K1 extends keyof O
17+
> = O[K1] extends object ? keyof O[K1] : never;
18+
19+
type keys2workaround<O extends DeepObject, K1 extends keyof O> = Extract<
20+
O[K1] extends object ? keyof O[K1] : never,
21+
string
22+
>;
23+
24+
interface Foo extends DeepObject {
25+
a: {
26+
"1": 123;
27+
"2": string;
28+
"3": boolean;
29+
};
30+
}
31+
32+
class Bar<O extends DeepObject> {
33+
broken<
34+
K1 extends keyof O,
35+
K2 extends keys2broken<O, K1>,
36+
V extends O[K1][K2]
37+
>(k1: K1, k2: K2, value: V) {}
38+
39+
working<
40+
K1 extends keyof O,
41+
K2 extends keys2working<O, K1>,
42+
V extends O[K1][K2]
43+
>(k1: K1, k2: K2, value: V) {}
44+
45+
workaround<
46+
K1 extends keyof O,
47+
K2 extends keys2workaround<O, K1>,
48+
V extends O[K1][K2]
49+
>(k1: K1, k2: K2, value: V) {}
50+
}
51+
52+
const bar = new Bar<Foo>();
53+
// all 3 of the below should error on passing `true` for `"1"`
54+
bar.broken("a", "1", true); // was broken in the past - with 2nd argument incorrectly of type "1" | "2" | "3".
55+
bar.working("a", "1", true); // ok - true is not allowed
56+
bar.workaround("a", "1", true); // ok - true is not allowed
57+
58+
59+
//// [deepKeysIndexing.js]
60+
var Bar = /** @class */ (function () {
61+
function Bar() {
62+
}
63+
Bar.prototype.broken = function (k1, k2, value) { };
64+
Bar.prototype.working = function (k1, k2, value) { };
65+
Bar.prototype.workaround = function (k1, k2, value) { };
66+
return Bar;
67+
}());
68+
var bar = new Bar();
69+
// all 3 of the below should error on passing `true` for `"1"`
70+
bar.broken("a", "1", true); // was broken in the past - with 2nd argument incorrectly of type "1" | "2" | "3".
71+
bar.working("a", "1", true); // ok - true is not allowed
72+
bar.workaround("a", "1", true); // ok - true is not allowed
Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
=== tests/cases/compiler/deepKeysIndexing.ts ===
2+
// regression test from https://github.com/Microsoft/TypeScript/issues/29692
3+
interface DeepObject {
4+
>DeepObject : Symbol(DeepObject, Decl(deepKeysIndexing.ts, 0, 0))
5+
6+
[k1: string]: {
7+
>k1 : Symbol(k1, Decl(deepKeysIndexing.ts, 2, 3))
8+
9+
[k2: string]: any;
10+
>k2 : Symbol(k2, Decl(deepKeysIndexing.ts, 3, 5))
11+
12+
};
13+
}
14+
15+
type keys2broken<
16+
>keys2broken : Symbol(keys2broken, Decl(deepKeysIndexing.ts, 5, 1))
17+
18+
O extends DeepObject,
19+
>O : Symbol(O, Decl(deepKeysIndexing.ts, 7, 17))
20+
>DeepObject : Symbol(DeepObject, Decl(deepKeysIndexing.ts, 0, 0))
21+
22+
K1 extends keyof O
23+
>K1 : Symbol(K1, Decl(deepKeysIndexing.ts, 8, 23))
24+
>O : Symbol(O, Decl(deepKeysIndexing.ts, 7, 17))
25+
26+
> = O[K1] extends object ? Extract<keyof O[K1], string> : never;
27+
>O : Symbol(O, Decl(deepKeysIndexing.ts, 7, 17))
28+
>K1 : Symbol(K1, Decl(deepKeysIndexing.ts, 8, 23))
29+
>Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --))
30+
>O : Symbol(O, Decl(deepKeysIndexing.ts, 7, 17))
31+
>K1 : Symbol(K1, Decl(deepKeysIndexing.ts, 8, 23))
32+
33+
type keys2working<
34+
>keys2working : Symbol(keys2working, Decl(deepKeysIndexing.ts, 10, 64))
35+
36+
O extends DeepObject,
37+
>O : Symbol(O, Decl(deepKeysIndexing.ts, 12, 18))
38+
>DeepObject : Symbol(DeepObject, Decl(deepKeysIndexing.ts, 0, 0))
39+
40+
K1 extends keyof O
41+
>K1 : Symbol(K1, Decl(deepKeysIndexing.ts, 13, 23))
42+
>O : Symbol(O, Decl(deepKeysIndexing.ts, 12, 18))
43+
44+
> = O[K1] extends object ? keyof O[K1] : never;
45+
>O : Symbol(O, Decl(deepKeysIndexing.ts, 12, 18))
46+
>K1 : Symbol(K1, Decl(deepKeysIndexing.ts, 13, 23))
47+
>O : Symbol(O, Decl(deepKeysIndexing.ts, 12, 18))
48+
>K1 : Symbol(K1, Decl(deepKeysIndexing.ts, 13, 23))
49+
50+
type keys2workaround<O extends DeepObject, K1 extends keyof O> = Extract<
51+
>keys2workaround : Symbol(keys2workaround, Decl(deepKeysIndexing.ts, 15, 47))
52+
>O : Symbol(O, Decl(deepKeysIndexing.ts, 17, 21))
53+
>DeepObject : Symbol(DeepObject, Decl(deepKeysIndexing.ts, 0, 0))
54+
>K1 : Symbol(K1, Decl(deepKeysIndexing.ts, 17, 42))
55+
>O : Symbol(O, Decl(deepKeysIndexing.ts, 17, 21))
56+
>Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --))
57+
58+
O[K1] extends object ? keyof O[K1] : never,
59+
>O : Symbol(O, Decl(deepKeysIndexing.ts, 17, 21))
60+
>K1 : Symbol(K1, Decl(deepKeysIndexing.ts, 17, 42))
61+
>O : Symbol(O, Decl(deepKeysIndexing.ts, 17, 21))
62+
>K1 : Symbol(K1, Decl(deepKeysIndexing.ts, 17, 42))
63+
64+
string
65+
>;
66+
67+
interface Foo extends DeepObject {
68+
>Foo : Symbol(Foo, Decl(deepKeysIndexing.ts, 20, 2))
69+
>DeepObject : Symbol(DeepObject, Decl(deepKeysIndexing.ts, 0, 0))
70+
71+
a: {
72+
>a : Symbol(Foo.a, Decl(deepKeysIndexing.ts, 22, 34))
73+
74+
"1": 123;
75+
>"1" : Symbol("1", Decl(deepKeysIndexing.ts, 23, 6))
76+
77+
"2": string;
78+
>"2" : Symbol("2", Decl(deepKeysIndexing.ts, 24, 13))
79+
80+
"3": boolean;
81+
>"3" : Symbol("3", Decl(deepKeysIndexing.ts, 25, 16))
82+
83+
};
84+
}
85+
86+
class Bar<O extends DeepObject> {
87+
>Bar : Symbol(Bar, Decl(deepKeysIndexing.ts, 28, 1))
88+
>O : Symbol(O, Decl(deepKeysIndexing.ts, 30, 10))
89+
>DeepObject : Symbol(DeepObject, Decl(deepKeysIndexing.ts, 0, 0))
90+
91+
broken<
92+
>broken : Symbol(Bar.broken, Decl(deepKeysIndexing.ts, 30, 33))
93+
94+
K1 extends keyof O,
95+
>K1 : Symbol(K1, Decl(deepKeysIndexing.ts, 31, 9))
96+
>O : Symbol(O, Decl(deepKeysIndexing.ts, 30, 10))
97+
98+
K2 extends keys2broken<O, K1>,
99+
>K2 : Symbol(K2, Decl(deepKeysIndexing.ts, 32, 23))
100+
>keys2broken : Symbol(keys2broken, Decl(deepKeysIndexing.ts, 5, 1))
101+
>O : Symbol(O, Decl(deepKeysIndexing.ts, 30, 10))
102+
>K1 : Symbol(K1, Decl(deepKeysIndexing.ts, 31, 9))
103+
104+
V extends O[K1][K2]
105+
>V : Symbol(V, Decl(deepKeysIndexing.ts, 33, 34))
106+
>O : Symbol(O, Decl(deepKeysIndexing.ts, 30, 10))
107+
>K1 : Symbol(K1, Decl(deepKeysIndexing.ts, 31, 9))
108+
>K2 : Symbol(K2, Decl(deepKeysIndexing.ts, 32, 23))
109+
110+
>(k1: K1, k2: K2, value: V) {}
111+
>k1 : Symbol(k1, Decl(deepKeysIndexing.ts, 35, 4))
112+
>K1 : Symbol(K1, Decl(deepKeysIndexing.ts, 31, 9))
113+
>k2 : Symbol(k2, Decl(deepKeysIndexing.ts, 35, 11))
114+
>K2 : Symbol(K2, Decl(deepKeysIndexing.ts, 32, 23))
115+
>value : Symbol(value, Decl(deepKeysIndexing.ts, 35, 19))
116+
>V : Symbol(V, Decl(deepKeysIndexing.ts, 33, 34))
117+
118+
working<
119+
>working : Symbol(Bar.working, Decl(deepKeysIndexing.ts, 35, 32))
120+
121+
K1 extends keyof O,
122+
>K1 : Symbol(K1, Decl(deepKeysIndexing.ts, 37, 10))
123+
>O : Symbol(O, Decl(deepKeysIndexing.ts, 30, 10))
124+
125+
K2 extends keys2working<O, K1>,
126+
>K2 : Symbol(K2, Decl(deepKeysIndexing.ts, 38, 23))
127+
>keys2working : Symbol(keys2working, Decl(deepKeysIndexing.ts, 10, 64))
128+
>O : Symbol(O, Decl(deepKeysIndexing.ts, 30, 10))
129+
>K1 : Symbol(K1, Decl(deepKeysIndexing.ts, 37, 10))
130+
131+
V extends O[K1][K2]
132+
>V : Symbol(V, Decl(deepKeysIndexing.ts, 39, 35))
133+
>O : Symbol(O, Decl(deepKeysIndexing.ts, 30, 10))
134+
>K1 : Symbol(K1, Decl(deepKeysIndexing.ts, 37, 10))
135+
>K2 : Symbol(K2, Decl(deepKeysIndexing.ts, 38, 23))
136+
137+
>(k1: K1, k2: K2, value: V) {}
138+
>k1 : Symbol(k1, Decl(deepKeysIndexing.ts, 41, 4))
139+
>K1 : Symbol(K1, Decl(deepKeysIndexing.ts, 37, 10))
140+
>k2 : Symbol(k2, Decl(deepKeysIndexing.ts, 41, 11))
141+
>K2 : Symbol(K2, Decl(deepKeysIndexing.ts, 38, 23))
142+
>value : Symbol(value, Decl(deepKeysIndexing.ts, 41, 19))
143+
>V : Symbol(V, Decl(deepKeysIndexing.ts, 39, 35))
144+
145+
workaround<
146+
>workaround : Symbol(Bar.workaround, Decl(deepKeysIndexing.ts, 41, 32))
147+
148+
K1 extends keyof O,
149+
>K1 : Symbol(K1, Decl(deepKeysIndexing.ts, 43, 13))
150+
>O : Symbol(O, Decl(deepKeysIndexing.ts, 30, 10))
151+
152+
K2 extends keys2workaround<O, K1>,
153+
>K2 : Symbol(K2, Decl(deepKeysIndexing.ts, 44, 23))
154+
>keys2workaround : Symbol(keys2workaround, Decl(deepKeysIndexing.ts, 15, 47))
155+
>O : Symbol(O, Decl(deepKeysIndexing.ts, 30, 10))
156+
>K1 : Symbol(K1, Decl(deepKeysIndexing.ts, 43, 13))
157+
158+
V extends O[K1][K2]
159+
>V : Symbol(V, Decl(deepKeysIndexing.ts, 45, 38))
160+
>O : Symbol(O, Decl(deepKeysIndexing.ts, 30, 10))
161+
>K1 : Symbol(K1, Decl(deepKeysIndexing.ts, 43, 13))
162+
>K2 : Symbol(K2, Decl(deepKeysIndexing.ts, 44, 23))
163+
164+
>(k1: K1, k2: K2, value: V) {}
165+
>k1 : Symbol(k1, Decl(deepKeysIndexing.ts, 47, 4))
166+
>K1 : Symbol(K1, Decl(deepKeysIndexing.ts, 43, 13))
167+
>k2 : Symbol(k2, Decl(deepKeysIndexing.ts, 47, 11))
168+
>K2 : Symbol(K2, Decl(deepKeysIndexing.ts, 44, 23))
169+
>value : Symbol(value, Decl(deepKeysIndexing.ts, 47, 19))
170+
>V : Symbol(V, Decl(deepKeysIndexing.ts, 45, 38))
171+
}
172+
173+
const bar = new Bar<Foo>();
174+
>bar : Symbol(bar, Decl(deepKeysIndexing.ts, 50, 5))
175+
>Bar : Symbol(Bar, Decl(deepKeysIndexing.ts, 28, 1))
176+
>Foo : Symbol(Foo, Decl(deepKeysIndexing.ts, 20, 2))
177+
178+
// all 3 of the below should error on passing `true` for `"1"`
179+
bar.broken("a", "1", true); // was broken in the past - with 2nd argument incorrectly of type "1" | "2" | "3".
180+
>bar.broken : Symbol(Bar.broken, Decl(deepKeysIndexing.ts, 30, 33))
181+
>bar : Symbol(bar, Decl(deepKeysIndexing.ts, 50, 5))
182+
>broken : Symbol(Bar.broken, Decl(deepKeysIndexing.ts, 30, 33))
183+
184+
bar.working("a", "1", true); // ok - true is not allowed
185+
>bar.working : Symbol(Bar.working, Decl(deepKeysIndexing.ts, 35, 32))
186+
>bar : Symbol(bar, Decl(deepKeysIndexing.ts, 50, 5))
187+
>working : Symbol(Bar.working, Decl(deepKeysIndexing.ts, 35, 32))
188+
189+
bar.workaround("a", "1", true); // ok - true is not allowed
190+
>bar.workaround : Symbol(Bar.workaround, Decl(deepKeysIndexing.ts, 41, 32))
191+
>bar : Symbol(bar, Decl(deepKeysIndexing.ts, 50, 5))
192+
>workaround : Symbol(Bar.workaround, Decl(deepKeysIndexing.ts, 41, 32))
193+

0 commit comments

Comments
 (0)