From 55d4d7b5c637c33f175b22458df3ff2302474621 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sun, 3 Jun 2018 08:57:15 -0700 Subject: [PATCH 1/3] Simplify nested indexed access types --- src/compiler/checker.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 9306907b418..b1ac56d66eb 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -8881,7 +8881,9 @@ namespace ts { return type.simplified === circularConstraintType ? type : type.simplified; } type.simplified = circularConstraintType; - const objectType = type.objectType; + // We recursively simplify the object type as it may in turn be an indexed access type. For example, with + // '{ [P in T]: { [Q in U]: number } }[T][U]' we want to first simplify the inner indexed access type. + const objectType = getSimplifiedType(type.objectType); if (objectType.flags & TypeFlags.Intersection && isGenericObjectType(objectType)) { // Given an indexed access type T[K], if T is an intersection containing one or more generic types and one or // more object types with only a string index signature, e.g. '(U & V & { [x: string]: D })[K]', return a From 54f9c170450a0bb7698460d235850703e8205b61 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sun, 3 Jun 2018 11:59:24 -0700 Subject: [PATCH 2/3] Add regression test --- .../types/keyof/keyofAndIndexedAccess.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tests/cases/conformance/types/keyof/keyofAndIndexedAccess.ts b/tests/cases/conformance/types/keyof/keyofAndIndexedAccess.ts index 07aa3c1994f..c76071f7d99 100644 --- a/tests/cases/conformance/types/keyof/keyofAndIndexedAccess.ts +++ b/tests/cases/conformance/types/keyof/keyofAndIndexedAccess.ts @@ -637,3 +637,17 @@ interface I7 { } type Foo7 = T; declare function f7(type: K): Foo7; + +// Repro from #21770 + +type Dict = { [key in T]: number }; +type DictDict = { [key in V]: Dict }; + +function ff1(dd: DictDict, k1: V, k2: T): number { + return dd[k1][k2]; +} + +function ff2(dd: DictDict, k1: V, k2: T): number { + const d: Dict = dd[k1]; + return d[k2]; +} From 9eea4d53edc024a880f4e852588ff3231b3084c0 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sun, 3 Jun 2018 11:59:32 -0700 Subject: [PATCH 3/3] Accept new baselines --- .../reference/keyofAndIndexedAccess.js | 29 +++++++++ .../reference/keyofAndIndexedAccess.symbols | 61 +++++++++++++++++ .../reference/keyofAndIndexedAccess.types | 65 +++++++++++++++++++ 3 files changed, 155 insertions(+) diff --git a/tests/baselines/reference/keyofAndIndexedAccess.js b/tests/baselines/reference/keyofAndIndexedAccess.js index c23f10f3e68..3667a30f92c 100644 --- a/tests/baselines/reference/keyofAndIndexedAccess.js +++ b/tests/baselines/reference/keyofAndIndexedAccess.js @@ -635,6 +635,20 @@ interface I7 { } type Foo7 = T; declare function f7(type: K): Foo7; + +// Repro from #21770 + +type Dict = { [key in T]: number }; +type DictDict = { [key in V]: Dict }; + +function ff1(dd: DictDict, k1: V, k2: T): number { + return dd[k1][k2]; +} + +function ff2(dd: DictDict, k1: V, k2: T): number { + const d: Dict = dd[k1]; + return d[k2]; +} //// [keyofAndIndexedAccess.js] @@ -1054,6 +1068,13 @@ var Unbounded = /** @class */ (function () { }; return Unbounded; }()); +function ff1(dd, k1, k2) { + return dd[k1][k2]; +} +function ff2(dd, k1, k2) { + var d = dd[k1]; + return d[k2]; +} //// [keyofAndIndexedAccess.d.ts] @@ -1381,3 +1402,11 @@ interface I7 { } declare type Foo7 = T; declare function f7(type: K): Foo7; +declare type Dict = { + [key in T]: number; +}; +declare type DictDict = { + [key in V]: Dict; +}; +declare function ff1(dd: DictDict, k1: V, k2: T): number; +declare function ff2(dd: DictDict, k1: V, k2: T): number; diff --git a/tests/baselines/reference/keyofAndIndexedAccess.symbols b/tests/baselines/reference/keyofAndIndexedAccess.symbols index ef43a711264..de9a4be5947 100644 --- a/tests/baselines/reference/keyofAndIndexedAccess.symbols +++ b/tests/baselines/reference/keyofAndIndexedAccess.symbols @@ -2258,3 +2258,64 @@ declare function f7(type: K): Foo7; >I7 : Symbol(I7, Decl(keyofAndIndexedAccess.ts, 627, 1)) >K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 635, 20)) +// Repro from #21770 + +type Dict = { [key in T]: number }; +>Dict : Symbol(Dict, Decl(keyofAndIndexedAccess.ts, 635, 62)) +>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 639, 10)) +>key : Symbol(key, Decl(keyofAndIndexedAccess.ts, 639, 33)) +>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 639, 10)) + +type DictDict = { [key in V]: Dict }; +>DictDict : Symbol(DictDict, Decl(keyofAndIndexedAccess.ts, 639, 53)) +>V : Symbol(V, Decl(keyofAndIndexedAccess.ts, 640, 14)) +>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 640, 31)) +>key : Symbol(key, Decl(keyofAndIndexedAccess.ts, 640, 55)) +>V : Symbol(V, Decl(keyofAndIndexedAccess.ts, 640, 14)) +>Dict : Symbol(Dict, Decl(keyofAndIndexedAccess.ts, 635, 62)) +>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 640, 31)) + +function ff1(dd: DictDict, k1: V, k2: T): number { +>ff1 : Symbol(ff1, Decl(keyofAndIndexedAccess.ts, 640, 76)) +>V : Symbol(V, Decl(keyofAndIndexedAccess.ts, 642, 13)) +>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 642, 30)) +>dd : Symbol(dd, Decl(keyofAndIndexedAccess.ts, 642, 49)) +>DictDict : Symbol(DictDict, Decl(keyofAndIndexedAccess.ts, 639, 53)) +>V : Symbol(V, Decl(keyofAndIndexedAccess.ts, 642, 13)) +>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 642, 30)) +>k1 : Symbol(k1, Decl(keyofAndIndexedAccess.ts, 642, 68)) +>V : Symbol(V, Decl(keyofAndIndexedAccess.ts, 642, 13)) +>k2 : Symbol(k2, Decl(keyofAndIndexedAccess.ts, 642, 75)) +>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 642, 30)) + + return dd[k1][k2]; +>dd : Symbol(dd, Decl(keyofAndIndexedAccess.ts, 642, 49)) +>k1 : Symbol(k1, Decl(keyofAndIndexedAccess.ts, 642, 68)) +>k2 : Symbol(k2, Decl(keyofAndIndexedAccess.ts, 642, 75)) +} + +function ff2(dd: DictDict, k1: V, k2: T): number { +>ff2 : Symbol(ff2, Decl(keyofAndIndexedAccess.ts, 644, 1)) +>V : Symbol(V, Decl(keyofAndIndexedAccess.ts, 646, 13)) +>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 646, 30)) +>dd : Symbol(dd, Decl(keyofAndIndexedAccess.ts, 646, 49)) +>DictDict : Symbol(DictDict, Decl(keyofAndIndexedAccess.ts, 639, 53)) +>V : Symbol(V, Decl(keyofAndIndexedAccess.ts, 646, 13)) +>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 646, 30)) +>k1 : Symbol(k1, Decl(keyofAndIndexedAccess.ts, 646, 68)) +>V : Symbol(V, Decl(keyofAndIndexedAccess.ts, 646, 13)) +>k2 : Symbol(k2, Decl(keyofAndIndexedAccess.ts, 646, 75)) +>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 646, 30)) + + const d: Dict = dd[k1]; +>d : Symbol(d, Decl(keyofAndIndexedAccess.ts, 647, 9)) +>Dict : Symbol(Dict, Decl(keyofAndIndexedAccess.ts, 635, 62)) +>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 646, 30)) +>dd : Symbol(dd, Decl(keyofAndIndexedAccess.ts, 646, 49)) +>k1 : Symbol(k1, Decl(keyofAndIndexedAccess.ts, 646, 68)) + + return d[k2]; +>d : Symbol(d, Decl(keyofAndIndexedAccess.ts, 647, 9)) +>k2 : Symbol(k2, Decl(keyofAndIndexedAccess.ts, 646, 75)) +} + diff --git a/tests/baselines/reference/keyofAndIndexedAccess.types b/tests/baselines/reference/keyofAndIndexedAccess.types index a85b34d707b..1a65dbb0389 100644 --- a/tests/baselines/reference/keyofAndIndexedAccess.types +++ b/tests/baselines/reference/keyofAndIndexedAccess.types @@ -2614,3 +2614,68 @@ declare function f7(type: K): Foo7; >I7 : I7 >K : K +// Repro from #21770 + +type Dict = { [key in T]: number }; +>Dict : Dict +>T : T +>key : key +>T : T + +type DictDict = { [key in V]: Dict }; +>DictDict : DictDict +>V : V +>T : T +>key : key +>V : V +>Dict : Dict +>T : T + +function ff1(dd: DictDict, k1: V, k2: T): number { +>ff1 : (dd: DictDict, k1: V, k2: T) => number +>V : V +>T : T +>dd : DictDict +>DictDict : DictDict +>V : V +>T : T +>k1 : V +>V : V +>k2 : T +>T : T + + return dd[k1][k2]; +>dd[k1][k2] : DictDict[V][T] +>dd[k1] : DictDict[V] +>dd : DictDict +>k1 : V +>k2 : T +} + +function ff2(dd: DictDict, k1: V, k2: T): number { +>ff2 : (dd: DictDict, k1: V, k2: T) => number +>V : V +>T : T +>dd : DictDict +>DictDict : DictDict +>V : V +>T : T +>k1 : V +>V : V +>k2 : T +>T : T + + const d: Dict = dd[k1]; +>d : Dict +>Dict : Dict +>T : T +>dd[k1] : DictDict[V] +>dd : DictDict +>k1 : V + + return d[k2]; +>d[k2] : Dict[T] +>d : Dict +>k2 : T +} +