mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-20 19:45:07 -06:00
parent
ca9566fcde
commit
3ba5aa9f60
68
tests/baselines/reference/deepKeysIndexing.errors.txt
Normal file
68
tests/baselines/reference/deepKeysIndexing.errors.txt
Normal file
@ -0,0 +1,68 @@
|
||||
tests/cases/compiler/deepKeysIndexing.ts(53,22): error TS2345: Argument of type 'true' is not assignable to parameter of type '123'.
|
||||
tests/cases/compiler/deepKeysIndexing.ts(54,23): error TS2345: Argument of type 'true' is not assignable to parameter of type '123'.
|
||||
tests/cases/compiler/deepKeysIndexing.ts(55,26): error TS2345: Argument of type 'true' is not assignable to parameter of type '123'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/deepKeysIndexing.ts (3 errors) ====
|
||||
// regression test from https://github.com/Microsoft/TypeScript/issues/29692
|
||||
interface DeepObject {
|
||||
[k1: string]: {
|
||||
[k2: string]: any;
|
||||
};
|
||||
}
|
||||
|
||||
type keys2broken<
|
||||
O extends DeepObject,
|
||||
K1 extends keyof O
|
||||
> = O[K1] extends object ? Extract<keyof O[K1], string> : never;
|
||||
|
||||
type keys2working<
|
||||
O extends DeepObject,
|
||||
K1 extends keyof O
|
||||
> = O[K1] extends object ? keyof O[K1] : never;
|
||||
|
||||
type keys2workaround<O extends DeepObject, K1 extends keyof O> = Extract<
|
||||
O[K1] extends object ? keyof O[K1] : never,
|
||||
string
|
||||
>;
|
||||
|
||||
interface Foo extends DeepObject {
|
||||
a: {
|
||||
"1": 123;
|
||||
"2": string;
|
||||
"3": boolean;
|
||||
};
|
||||
}
|
||||
|
||||
class Bar<O extends DeepObject> {
|
||||
broken<
|
||||
K1 extends keyof O,
|
||||
K2 extends keys2broken<O, K1>,
|
||||
V extends O[K1][K2]
|
||||
>(k1: K1, k2: K2, value: V) {}
|
||||
|
||||
working<
|
||||
K1 extends keyof O,
|
||||
K2 extends keys2working<O, K1>,
|
||||
V extends O[K1][K2]
|
||||
>(k1: K1, k2: K2, value: V) {}
|
||||
|
||||
workaround<
|
||||
K1 extends keyof O,
|
||||
K2 extends keys2workaround<O, K1>,
|
||||
V extends O[K1][K2]
|
||||
>(k1: K1, k2: K2, value: V) {}
|
||||
}
|
||||
|
||||
const bar = new Bar<Foo>();
|
||||
// all 3 of the below should error on passing `true` for `"1"`
|
||||
bar.broken("a", "1", true); // was broken in the past - with 2nd argument incorrectly of type "1" | "2" | "3".
|
||||
~~~~
|
||||
!!! error TS2345: Argument of type 'true' is not assignable to parameter of type '123'.
|
||||
bar.working("a", "1", true); // ok - true is not allowed
|
||||
~~~~
|
||||
!!! error TS2345: Argument of type 'true' is not assignable to parameter of type '123'.
|
||||
bar.workaround("a", "1", true); // ok - true is not allowed
|
||||
~~~~
|
||||
!!! error TS2345: Argument of type 'true' is not assignable to parameter of type '123'.
|
||||
|
||||
72
tests/baselines/reference/deepKeysIndexing.js
Normal file
72
tests/baselines/reference/deepKeysIndexing.js
Normal file
@ -0,0 +1,72 @@
|
||||
//// [deepKeysIndexing.ts]
|
||||
// regression test from https://github.com/Microsoft/TypeScript/issues/29692
|
||||
interface DeepObject {
|
||||
[k1: string]: {
|
||||
[k2: string]: any;
|
||||
};
|
||||
}
|
||||
|
||||
type keys2broken<
|
||||
O extends DeepObject,
|
||||
K1 extends keyof O
|
||||
> = O[K1] extends object ? Extract<keyof O[K1], string> : never;
|
||||
|
||||
type keys2working<
|
||||
O extends DeepObject,
|
||||
K1 extends keyof O
|
||||
> = O[K1] extends object ? keyof O[K1] : never;
|
||||
|
||||
type keys2workaround<O extends DeepObject, K1 extends keyof O> = Extract<
|
||||
O[K1] extends object ? keyof O[K1] : never,
|
||||
string
|
||||
>;
|
||||
|
||||
interface Foo extends DeepObject {
|
||||
a: {
|
||||
"1": 123;
|
||||
"2": string;
|
||||
"3": boolean;
|
||||
};
|
||||
}
|
||||
|
||||
class Bar<O extends DeepObject> {
|
||||
broken<
|
||||
K1 extends keyof O,
|
||||
K2 extends keys2broken<O, K1>,
|
||||
V extends O[K1][K2]
|
||||
>(k1: K1, k2: K2, value: V) {}
|
||||
|
||||
working<
|
||||
K1 extends keyof O,
|
||||
K2 extends keys2working<O, K1>,
|
||||
V extends O[K1][K2]
|
||||
>(k1: K1, k2: K2, value: V) {}
|
||||
|
||||
workaround<
|
||||
K1 extends keyof O,
|
||||
K2 extends keys2workaround<O, K1>,
|
||||
V extends O[K1][K2]
|
||||
>(k1: K1, k2: K2, value: V) {}
|
||||
}
|
||||
|
||||
const bar = new Bar<Foo>();
|
||||
// all 3 of the below should error on passing `true` for `"1"`
|
||||
bar.broken("a", "1", true); // was broken in the past - with 2nd argument incorrectly of type "1" | "2" | "3".
|
||||
bar.working("a", "1", true); // ok - true is not allowed
|
||||
bar.workaround("a", "1", true); // ok - true is not allowed
|
||||
|
||||
|
||||
//// [deepKeysIndexing.js]
|
||||
var Bar = /** @class */ (function () {
|
||||
function Bar() {
|
||||
}
|
||||
Bar.prototype.broken = function (k1, k2, value) { };
|
||||
Bar.prototype.working = function (k1, k2, value) { };
|
||||
Bar.prototype.workaround = function (k1, k2, value) { };
|
||||
return Bar;
|
||||
}());
|
||||
var bar = new Bar();
|
||||
// all 3 of the below should error on passing `true` for `"1"`
|
||||
bar.broken("a", "1", true); // was broken in the past - with 2nd argument incorrectly of type "1" | "2" | "3".
|
||||
bar.working("a", "1", true); // ok - true is not allowed
|
||||
bar.workaround("a", "1", true); // ok - true is not allowed
|
||||
193
tests/baselines/reference/deepKeysIndexing.symbols
Normal file
193
tests/baselines/reference/deepKeysIndexing.symbols
Normal file
@ -0,0 +1,193 @@
|
||||
=== tests/cases/compiler/deepKeysIndexing.ts ===
|
||||
// regression test from https://github.com/Microsoft/TypeScript/issues/29692
|
||||
interface DeepObject {
|
||||
>DeepObject : Symbol(DeepObject, Decl(deepKeysIndexing.ts, 0, 0))
|
||||
|
||||
[k1: string]: {
|
||||
>k1 : Symbol(k1, Decl(deepKeysIndexing.ts, 2, 3))
|
||||
|
||||
[k2: string]: any;
|
||||
>k2 : Symbol(k2, Decl(deepKeysIndexing.ts, 3, 5))
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
type keys2broken<
|
||||
>keys2broken : Symbol(keys2broken, Decl(deepKeysIndexing.ts, 5, 1))
|
||||
|
||||
O extends DeepObject,
|
||||
>O : Symbol(O, Decl(deepKeysIndexing.ts, 7, 17))
|
||||
>DeepObject : Symbol(DeepObject, Decl(deepKeysIndexing.ts, 0, 0))
|
||||
|
||||
K1 extends keyof O
|
||||
>K1 : Symbol(K1, Decl(deepKeysIndexing.ts, 8, 23))
|
||||
>O : Symbol(O, Decl(deepKeysIndexing.ts, 7, 17))
|
||||
|
||||
> = O[K1] extends object ? Extract<keyof O[K1], string> : never;
|
||||
>O : Symbol(O, Decl(deepKeysIndexing.ts, 7, 17))
|
||||
>K1 : Symbol(K1, Decl(deepKeysIndexing.ts, 8, 23))
|
||||
>Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --))
|
||||
>O : Symbol(O, Decl(deepKeysIndexing.ts, 7, 17))
|
||||
>K1 : Symbol(K1, Decl(deepKeysIndexing.ts, 8, 23))
|
||||
|
||||
type keys2working<
|
||||
>keys2working : Symbol(keys2working, Decl(deepKeysIndexing.ts, 10, 64))
|
||||
|
||||
O extends DeepObject,
|
||||
>O : Symbol(O, Decl(deepKeysIndexing.ts, 12, 18))
|
||||
>DeepObject : Symbol(DeepObject, Decl(deepKeysIndexing.ts, 0, 0))
|
||||
|
||||
K1 extends keyof O
|
||||
>K1 : Symbol(K1, Decl(deepKeysIndexing.ts, 13, 23))
|
||||
>O : Symbol(O, Decl(deepKeysIndexing.ts, 12, 18))
|
||||
|
||||
> = O[K1] extends object ? keyof O[K1] : never;
|
||||
>O : Symbol(O, Decl(deepKeysIndexing.ts, 12, 18))
|
||||
>K1 : Symbol(K1, Decl(deepKeysIndexing.ts, 13, 23))
|
||||
>O : Symbol(O, Decl(deepKeysIndexing.ts, 12, 18))
|
||||
>K1 : Symbol(K1, Decl(deepKeysIndexing.ts, 13, 23))
|
||||
|
||||
type keys2workaround<O extends DeepObject, K1 extends keyof O> = Extract<
|
||||
>keys2workaround : Symbol(keys2workaround, Decl(deepKeysIndexing.ts, 15, 47))
|
||||
>O : Symbol(O, Decl(deepKeysIndexing.ts, 17, 21))
|
||||
>DeepObject : Symbol(DeepObject, Decl(deepKeysIndexing.ts, 0, 0))
|
||||
>K1 : Symbol(K1, Decl(deepKeysIndexing.ts, 17, 42))
|
||||
>O : Symbol(O, Decl(deepKeysIndexing.ts, 17, 21))
|
||||
>Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --))
|
||||
|
||||
O[K1] extends object ? keyof O[K1] : never,
|
||||
>O : Symbol(O, Decl(deepKeysIndexing.ts, 17, 21))
|
||||
>K1 : Symbol(K1, Decl(deepKeysIndexing.ts, 17, 42))
|
||||
>O : Symbol(O, Decl(deepKeysIndexing.ts, 17, 21))
|
||||
>K1 : Symbol(K1, Decl(deepKeysIndexing.ts, 17, 42))
|
||||
|
||||
string
|
||||
>;
|
||||
|
||||
interface Foo extends DeepObject {
|
||||
>Foo : Symbol(Foo, Decl(deepKeysIndexing.ts, 20, 2))
|
||||
>DeepObject : Symbol(DeepObject, Decl(deepKeysIndexing.ts, 0, 0))
|
||||
|
||||
a: {
|
||||
>a : Symbol(Foo.a, Decl(deepKeysIndexing.ts, 22, 34))
|
||||
|
||||
"1": 123;
|
||||
>"1" : Symbol("1", Decl(deepKeysIndexing.ts, 23, 6))
|
||||
|
||||
"2": string;
|
||||
>"2" : Symbol("2", Decl(deepKeysIndexing.ts, 24, 13))
|
||||
|
||||
"3": boolean;
|
||||
>"3" : Symbol("3", Decl(deepKeysIndexing.ts, 25, 16))
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
class Bar<O extends DeepObject> {
|
||||
>Bar : Symbol(Bar, Decl(deepKeysIndexing.ts, 28, 1))
|
||||
>O : Symbol(O, Decl(deepKeysIndexing.ts, 30, 10))
|
||||
>DeepObject : Symbol(DeepObject, Decl(deepKeysIndexing.ts, 0, 0))
|
||||
|
||||
broken<
|
||||
>broken : Symbol(Bar.broken, Decl(deepKeysIndexing.ts, 30, 33))
|
||||
|
||||
K1 extends keyof O,
|
||||
>K1 : Symbol(K1, Decl(deepKeysIndexing.ts, 31, 9))
|
||||
>O : Symbol(O, Decl(deepKeysIndexing.ts, 30, 10))
|
||||
|
||||
K2 extends keys2broken<O, K1>,
|
||||
>K2 : Symbol(K2, Decl(deepKeysIndexing.ts, 32, 23))
|
||||
>keys2broken : Symbol(keys2broken, Decl(deepKeysIndexing.ts, 5, 1))
|
||||
>O : Symbol(O, Decl(deepKeysIndexing.ts, 30, 10))
|
||||
>K1 : Symbol(K1, Decl(deepKeysIndexing.ts, 31, 9))
|
||||
|
||||
V extends O[K1][K2]
|
||||
>V : Symbol(V, Decl(deepKeysIndexing.ts, 33, 34))
|
||||
>O : Symbol(O, Decl(deepKeysIndexing.ts, 30, 10))
|
||||
>K1 : Symbol(K1, Decl(deepKeysIndexing.ts, 31, 9))
|
||||
>K2 : Symbol(K2, Decl(deepKeysIndexing.ts, 32, 23))
|
||||
|
||||
>(k1: K1, k2: K2, value: V) {}
|
||||
>k1 : Symbol(k1, Decl(deepKeysIndexing.ts, 35, 4))
|
||||
>K1 : Symbol(K1, Decl(deepKeysIndexing.ts, 31, 9))
|
||||
>k2 : Symbol(k2, Decl(deepKeysIndexing.ts, 35, 11))
|
||||
>K2 : Symbol(K2, Decl(deepKeysIndexing.ts, 32, 23))
|
||||
>value : Symbol(value, Decl(deepKeysIndexing.ts, 35, 19))
|
||||
>V : Symbol(V, Decl(deepKeysIndexing.ts, 33, 34))
|
||||
|
||||
working<
|
||||
>working : Symbol(Bar.working, Decl(deepKeysIndexing.ts, 35, 32))
|
||||
|
||||
K1 extends keyof O,
|
||||
>K1 : Symbol(K1, Decl(deepKeysIndexing.ts, 37, 10))
|
||||
>O : Symbol(O, Decl(deepKeysIndexing.ts, 30, 10))
|
||||
|
||||
K2 extends keys2working<O, K1>,
|
||||
>K2 : Symbol(K2, Decl(deepKeysIndexing.ts, 38, 23))
|
||||
>keys2working : Symbol(keys2working, Decl(deepKeysIndexing.ts, 10, 64))
|
||||
>O : Symbol(O, Decl(deepKeysIndexing.ts, 30, 10))
|
||||
>K1 : Symbol(K1, Decl(deepKeysIndexing.ts, 37, 10))
|
||||
|
||||
V extends O[K1][K2]
|
||||
>V : Symbol(V, Decl(deepKeysIndexing.ts, 39, 35))
|
||||
>O : Symbol(O, Decl(deepKeysIndexing.ts, 30, 10))
|
||||
>K1 : Symbol(K1, Decl(deepKeysIndexing.ts, 37, 10))
|
||||
>K2 : Symbol(K2, Decl(deepKeysIndexing.ts, 38, 23))
|
||||
|
||||
>(k1: K1, k2: K2, value: V) {}
|
||||
>k1 : Symbol(k1, Decl(deepKeysIndexing.ts, 41, 4))
|
||||
>K1 : Symbol(K1, Decl(deepKeysIndexing.ts, 37, 10))
|
||||
>k2 : Symbol(k2, Decl(deepKeysIndexing.ts, 41, 11))
|
||||
>K2 : Symbol(K2, Decl(deepKeysIndexing.ts, 38, 23))
|
||||
>value : Symbol(value, Decl(deepKeysIndexing.ts, 41, 19))
|
||||
>V : Symbol(V, Decl(deepKeysIndexing.ts, 39, 35))
|
||||
|
||||
workaround<
|
||||
>workaround : Symbol(Bar.workaround, Decl(deepKeysIndexing.ts, 41, 32))
|
||||
|
||||
K1 extends keyof O,
|
||||
>K1 : Symbol(K1, Decl(deepKeysIndexing.ts, 43, 13))
|
||||
>O : Symbol(O, Decl(deepKeysIndexing.ts, 30, 10))
|
||||
|
||||
K2 extends keys2workaround<O, K1>,
|
||||
>K2 : Symbol(K2, Decl(deepKeysIndexing.ts, 44, 23))
|
||||
>keys2workaround : Symbol(keys2workaround, Decl(deepKeysIndexing.ts, 15, 47))
|
||||
>O : Symbol(O, Decl(deepKeysIndexing.ts, 30, 10))
|
||||
>K1 : Symbol(K1, Decl(deepKeysIndexing.ts, 43, 13))
|
||||
|
||||
V extends O[K1][K2]
|
||||
>V : Symbol(V, Decl(deepKeysIndexing.ts, 45, 38))
|
||||
>O : Symbol(O, Decl(deepKeysIndexing.ts, 30, 10))
|
||||
>K1 : Symbol(K1, Decl(deepKeysIndexing.ts, 43, 13))
|
||||
>K2 : Symbol(K2, Decl(deepKeysIndexing.ts, 44, 23))
|
||||
|
||||
>(k1: K1, k2: K2, value: V) {}
|
||||
>k1 : Symbol(k1, Decl(deepKeysIndexing.ts, 47, 4))
|
||||
>K1 : Symbol(K1, Decl(deepKeysIndexing.ts, 43, 13))
|
||||
>k2 : Symbol(k2, Decl(deepKeysIndexing.ts, 47, 11))
|
||||
>K2 : Symbol(K2, Decl(deepKeysIndexing.ts, 44, 23))
|
||||
>value : Symbol(value, Decl(deepKeysIndexing.ts, 47, 19))
|
||||
>V : Symbol(V, Decl(deepKeysIndexing.ts, 45, 38))
|
||||
}
|
||||
|
||||
const bar = new Bar<Foo>();
|
||||
>bar : Symbol(bar, Decl(deepKeysIndexing.ts, 50, 5))
|
||||
>Bar : Symbol(Bar, Decl(deepKeysIndexing.ts, 28, 1))
|
||||
>Foo : Symbol(Foo, Decl(deepKeysIndexing.ts, 20, 2))
|
||||
|
||||
// all 3 of the below should error on passing `true` for `"1"`
|
||||
bar.broken("a", "1", true); // was broken in the past - with 2nd argument incorrectly of type "1" | "2" | "3".
|
||||
>bar.broken : Symbol(Bar.broken, Decl(deepKeysIndexing.ts, 30, 33))
|
||||
>bar : Symbol(bar, Decl(deepKeysIndexing.ts, 50, 5))
|
||||
>broken : Symbol(Bar.broken, Decl(deepKeysIndexing.ts, 30, 33))
|
||||
|
||||
bar.working("a", "1", true); // ok - true is not allowed
|
||||
>bar.working : Symbol(Bar.working, Decl(deepKeysIndexing.ts, 35, 32))
|
||||
>bar : Symbol(bar, Decl(deepKeysIndexing.ts, 50, 5))
|
||||
>working : Symbol(Bar.working, Decl(deepKeysIndexing.ts, 35, 32))
|
||||
|
||||
bar.workaround("a", "1", true); // ok - true is not allowed
|
||||
>bar.workaround : Symbol(Bar.workaround, Decl(deepKeysIndexing.ts, 41, 32))
|
||||
>bar : Symbol(bar, Decl(deepKeysIndexing.ts, 50, 5))
|
||||
>workaround : Symbol(Bar.workaround, Decl(deepKeysIndexing.ts, 41, 32))
|
||||
|
||||
119
tests/baselines/reference/deepKeysIndexing.types
Normal file
119
tests/baselines/reference/deepKeysIndexing.types
Normal file
@ -0,0 +1,119 @@
|
||||
=== tests/cases/compiler/deepKeysIndexing.ts ===
|
||||
// regression test from https://github.com/Microsoft/TypeScript/issues/29692
|
||||
interface DeepObject {
|
||||
[k1: string]: {
|
||||
>k1 : string
|
||||
|
||||
[k2: string]: any;
|
||||
>k2 : string
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
type keys2broken<
|
||||
>keys2broken : keys2broken<O, K1>
|
||||
|
||||
O extends DeepObject,
|
||||
K1 extends keyof O
|
||||
> = O[K1] extends object ? Extract<keyof O[K1], string> : never;
|
||||
|
||||
type keys2working<
|
||||
>keys2working : keys2working<O, K1>
|
||||
|
||||
O extends DeepObject,
|
||||
K1 extends keyof O
|
||||
> = O[K1] extends object ? keyof O[K1] : never;
|
||||
|
||||
type keys2workaround<O extends DeepObject, K1 extends keyof O> = Extract<
|
||||
>keys2workaround : Extract<O[K1] extends object ? keyof O[K1] : never, string>
|
||||
|
||||
O[K1] extends object ? keyof O[K1] : never,
|
||||
string
|
||||
>;
|
||||
|
||||
interface Foo extends DeepObject {
|
||||
a: {
|
||||
>a : { "1": 123; "2": string; "3": boolean; }
|
||||
|
||||
"1": 123;
|
||||
>"1" : 123
|
||||
|
||||
"2": string;
|
||||
>"2" : string
|
||||
|
||||
"3": boolean;
|
||||
>"3" : boolean
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
class Bar<O extends DeepObject> {
|
||||
>Bar : Bar<O>
|
||||
|
||||
broken<
|
||||
>broken : <K1 extends keyof O, K2 extends keys2broken<O, K1>, V extends O[K1][K2]>(k1: K1, k2: K2, value: V) => void
|
||||
|
||||
K1 extends keyof O,
|
||||
K2 extends keys2broken<O, K1>,
|
||||
V extends O[K1][K2]
|
||||
>(k1: K1, k2: K2, value: V) {}
|
||||
>k1 : K1
|
||||
>k2 : K2
|
||||
>value : V
|
||||
|
||||
working<
|
||||
>working : <K1 extends keyof O, K2 extends keys2working<O, K1>, V extends O[K1][K2]>(k1: K1, k2: K2, value: V) => void
|
||||
|
||||
K1 extends keyof O,
|
||||
K2 extends keys2working<O, K1>,
|
||||
V extends O[K1][K2]
|
||||
>(k1: K1, k2: K2, value: V) {}
|
||||
>k1 : K1
|
||||
>k2 : K2
|
||||
>value : V
|
||||
|
||||
workaround<
|
||||
>workaround : <K1 extends keyof O, K2 extends Extract<O[K1] extends object ? keyof O[K1] : never, string>, V extends O[K1][K2]>(k1: K1, k2: K2, value: V) => void
|
||||
|
||||
K1 extends keyof O,
|
||||
K2 extends keys2workaround<O, K1>,
|
||||
V extends O[K1][K2]
|
||||
>(k1: K1, k2: K2, value: V) {}
|
||||
>k1 : K1
|
||||
>k2 : K2
|
||||
>value : V
|
||||
}
|
||||
|
||||
const bar = new Bar<Foo>();
|
||||
>bar : Bar<Foo>
|
||||
>new Bar<Foo>() : Bar<Foo>
|
||||
>Bar : typeof Bar
|
||||
|
||||
// all 3 of the below should error on passing `true` for `"1"`
|
||||
bar.broken("a", "1", true); // was broken in the past - with 2nd argument incorrectly of type "1" | "2" | "3".
|
||||
>bar.broken("a", "1", true) : any
|
||||
>bar.broken : <K1 extends string | number, K2 extends keys2broken<Foo, K1>, V extends Foo[K1][K2]>(k1: K1, k2: K2, value: V) => void
|
||||
>bar : Bar<Foo>
|
||||
>broken : <K1 extends string | number, K2 extends keys2broken<Foo, K1>, V extends Foo[K1][K2]>(k1: K1, k2: K2, value: V) => void
|
||||
>"a" : "a"
|
||||
>"1" : "1"
|
||||
>true : true
|
||||
|
||||
bar.working("a", "1", true); // ok - true is not allowed
|
||||
>bar.working("a", "1", true) : any
|
||||
>bar.working : <K1 extends string | number, K2 extends keys2working<Foo, K1>, V extends Foo[K1][K2]>(k1: K1, k2: K2, value: V) => void
|
||||
>bar : Bar<Foo>
|
||||
>working : <K1 extends string | number, K2 extends keys2working<Foo, K1>, V extends Foo[K1][K2]>(k1: K1, k2: K2, value: V) => void
|
||||
>"a" : "a"
|
||||
>"1" : "1"
|
||||
>true : true
|
||||
|
||||
bar.workaround("a", "1", true); // ok - true is not allowed
|
||||
>bar.workaround("a", "1", true) : any
|
||||
>bar.workaround : <K1 extends string | number, K2 extends Extract<Foo[K1] extends object ? keyof Foo[K1] : never, string>, V extends Foo[K1][K2]>(k1: K1, k2: K2, value: V) => void
|
||||
>bar : Bar<Foo>
|
||||
>workaround : <K1 extends string | number, K2 extends Extract<Foo[K1] extends object ? keyof Foo[K1] : never, string>, V extends Foo[K1][K2]>(k1: K1, k2: K2, value: V) => void
|
||||
>"a" : "a"
|
||||
>"1" : "1"
|
||||
>true : true
|
||||
|
||||
55
tests/cases/compiler/deepKeysIndexing.ts
Normal file
55
tests/cases/compiler/deepKeysIndexing.ts
Normal file
@ -0,0 +1,55 @@
|
||||
// regression test from https://github.com/Microsoft/TypeScript/issues/29692
|
||||
interface DeepObject {
|
||||
[k1: string]: {
|
||||
[k2: string]: any;
|
||||
};
|
||||
}
|
||||
|
||||
type keys2broken<
|
||||
O extends DeepObject,
|
||||
K1 extends keyof O
|
||||
> = O[K1] extends object ? Extract<keyof O[K1], string> : never;
|
||||
|
||||
type keys2working<
|
||||
O extends DeepObject,
|
||||
K1 extends keyof O
|
||||
> = O[K1] extends object ? keyof O[K1] : never;
|
||||
|
||||
type keys2workaround<O extends DeepObject, K1 extends keyof O> = Extract<
|
||||
O[K1] extends object ? keyof O[K1] : never,
|
||||
string
|
||||
>;
|
||||
|
||||
interface Foo extends DeepObject {
|
||||
a: {
|
||||
"1": 123;
|
||||
"2": string;
|
||||
"3": boolean;
|
||||
};
|
||||
}
|
||||
|
||||
class Bar<O extends DeepObject> {
|
||||
broken<
|
||||
K1 extends keyof O,
|
||||
K2 extends keys2broken<O, K1>,
|
||||
V extends O[K1][K2]
|
||||
>(k1: K1, k2: K2, value: V) {}
|
||||
|
||||
working<
|
||||
K1 extends keyof O,
|
||||
K2 extends keys2working<O, K1>,
|
||||
V extends O[K1][K2]
|
||||
>(k1: K1, k2: K2, value: V) {}
|
||||
|
||||
workaround<
|
||||
K1 extends keyof O,
|
||||
K2 extends keys2workaround<O, K1>,
|
||||
V extends O[K1][K2]
|
||||
>(k1: K1, k2: K2, value: V) {}
|
||||
}
|
||||
|
||||
const bar = new Bar<Foo>();
|
||||
// all 3 of the below should error on passing `true` for `"1"`
|
||||
bar.broken("a", "1", true); // was broken in the past - with 2nd argument incorrectly of type "1" | "2" | "3".
|
||||
bar.working("a", "1", true); // ok - true is not allowed
|
||||
bar.workaround("a", "1", true); // ok - true is not allowed
|
||||
Loading…
x
Reference in New Issue
Block a user