Skip to content

Commit 75d0852

Browse files
authored
Merge pull request microsoft#24637 from Microsoft/fixIndexedAccessSimplification
Fix indexed access simplification
2 parents d64608d + 9eea4d5 commit 75d0852

File tree

5 files changed

+172
-1
lines changed

5 files changed

+172
-1
lines changed

src/compiler/checker.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8881,7 +8881,9 @@ namespace ts {
88818881
return type.simplified === circularConstraintType ? type : type.simplified;
88828882
}
88838883
type.simplified = circularConstraintType;
8884-
const objectType = type.objectType;
8884+
// We recursively simplify the object type as it may in turn be an indexed access type. For example, with
8885+
// '{ [P in T]: { [Q in U]: number } }[T][U]' we want to first simplify the inner indexed access type.
8886+
const objectType = getSimplifiedType(type.objectType);
88858887
if (objectType.flags & TypeFlags.Intersection && isGenericObjectType(objectType)) {
88868888
// Given an indexed access type T[K], if T is an intersection containing one or more generic types and one or
88878889
// more object types with only a string index signature, e.g. '(U & V & { [x: string]: D })[K]', return a

tests/baselines/reference/keyofAndIndexedAccess.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -635,6 +635,20 @@ interface I7 {
635635
}
636636
type Foo7<T extends number> = T;
637637
declare function f7<K extends keyof I7>(type: K): Foo7<I7[K]>;
638+
639+
// Repro from #21770
640+
641+
type Dict<T extends string> = { [key in T]: number };
642+
type DictDict<V extends string, T extends string> = { [key in V]: Dict<T> };
643+
644+
function ff1<V extends string, T extends string>(dd: DictDict<V, T>, k1: V, k2: T): number {
645+
return dd[k1][k2];
646+
}
647+
648+
function ff2<V extends string, T extends string>(dd: DictDict<V, T>, k1: V, k2: T): number {
649+
const d: Dict<T> = dd[k1];
650+
return d[k2];
651+
}
638652

639653

640654
//// [keyofAndIndexedAccess.js]
@@ -1054,6 +1068,13 @@ var Unbounded = /** @class */ (function () {
10541068
};
10551069
return Unbounded;
10561070
}());
1071+
function ff1(dd, k1, k2) {
1072+
return dd[k1][k2];
1073+
}
1074+
function ff2(dd, k1, k2) {
1075+
var d = dd[k1];
1076+
return d[k2];
1077+
}
10571078

10581079

10591080
//// [keyofAndIndexedAccess.d.ts]
@@ -1381,3 +1402,11 @@ interface I7 {
13811402
}
13821403
declare type Foo7<T extends number> = T;
13831404
declare function f7<K extends keyof I7>(type: K): Foo7<I7[K]>;
1405+
declare type Dict<T extends string> = {
1406+
[key in T]: number;
1407+
};
1408+
declare type DictDict<V extends string, T extends string> = {
1409+
[key in V]: Dict<T>;
1410+
};
1411+
declare function ff1<V extends string, T extends string>(dd: DictDict<V, T>, k1: V, k2: T): number;
1412+
declare function ff2<V extends string, T extends string>(dd: DictDict<V, T>, k1: V, k2: T): number;

tests/baselines/reference/keyofAndIndexedAccess.symbols

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2258,3 +2258,64 @@ declare function f7<K extends keyof I7>(type: K): Foo7<I7[K]>;
22582258
>I7 : Symbol(I7, Decl(keyofAndIndexedAccess.ts, 627, 1))
22592259
>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 635, 20))
22602260

2261+
// Repro from #21770
2262+
2263+
type Dict<T extends string> = { [key in T]: number };
2264+
>Dict : Symbol(Dict, Decl(keyofAndIndexedAccess.ts, 635, 62))
2265+
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 639, 10))
2266+
>key : Symbol(key, Decl(keyofAndIndexedAccess.ts, 639, 33))
2267+
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 639, 10))
2268+
2269+
type DictDict<V extends string, T extends string> = { [key in V]: Dict<T> };
2270+
>DictDict : Symbol(DictDict, Decl(keyofAndIndexedAccess.ts, 639, 53))
2271+
>V : Symbol(V, Decl(keyofAndIndexedAccess.ts, 640, 14))
2272+
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 640, 31))
2273+
>key : Symbol(key, Decl(keyofAndIndexedAccess.ts, 640, 55))
2274+
>V : Symbol(V, Decl(keyofAndIndexedAccess.ts, 640, 14))
2275+
>Dict : Symbol(Dict, Decl(keyofAndIndexedAccess.ts, 635, 62))
2276+
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 640, 31))
2277+
2278+
function ff1<V extends string, T extends string>(dd: DictDict<V, T>, k1: V, k2: T): number {
2279+
>ff1 : Symbol(ff1, Decl(keyofAndIndexedAccess.ts, 640, 76))
2280+
>V : Symbol(V, Decl(keyofAndIndexedAccess.ts, 642, 13))
2281+
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 642, 30))
2282+
>dd : Symbol(dd, Decl(keyofAndIndexedAccess.ts, 642, 49))
2283+
>DictDict : Symbol(DictDict, Decl(keyofAndIndexedAccess.ts, 639, 53))
2284+
>V : Symbol(V, Decl(keyofAndIndexedAccess.ts, 642, 13))
2285+
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 642, 30))
2286+
>k1 : Symbol(k1, Decl(keyofAndIndexedAccess.ts, 642, 68))
2287+
>V : Symbol(V, Decl(keyofAndIndexedAccess.ts, 642, 13))
2288+
>k2 : Symbol(k2, Decl(keyofAndIndexedAccess.ts, 642, 75))
2289+
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 642, 30))
2290+
2291+
return dd[k1][k2];
2292+
>dd : Symbol(dd, Decl(keyofAndIndexedAccess.ts, 642, 49))
2293+
>k1 : Symbol(k1, Decl(keyofAndIndexedAccess.ts, 642, 68))
2294+
>k2 : Symbol(k2, Decl(keyofAndIndexedAccess.ts, 642, 75))
2295+
}
2296+
2297+
function ff2<V extends string, T extends string>(dd: DictDict<V, T>, k1: V, k2: T): number {
2298+
>ff2 : Symbol(ff2, Decl(keyofAndIndexedAccess.ts, 644, 1))
2299+
>V : Symbol(V, Decl(keyofAndIndexedAccess.ts, 646, 13))
2300+
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 646, 30))
2301+
>dd : Symbol(dd, Decl(keyofAndIndexedAccess.ts, 646, 49))
2302+
>DictDict : Symbol(DictDict, Decl(keyofAndIndexedAccess.ts, 639, 53))
2303+
>V : Symbol(V, Decl(keyofAndIndexedAccess.ts, 646, 13))
2304+
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 646, 30))
2305+
>k1 : Symbol(k1, Decl(keyofAndIndexedAccess.ts, 646, 68))
2306+
>V : Symbol(V, Decl(keyofAndIndexedAccess.ts, 646, 13))
2307+
>k2 : Symbol(k2, Decl(keyofAndIndexedAccess.ts, 646, 75))
2308+
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 646, 30))
2309+
2310+
const d: Dict<T> = dd[k1];
2311+
>d : Symbol(d, Decl(keyofAndIndexedAccess.ts, 647, 9))
2312+
>Dict : Symbol(Dict, Decl(keyofAndIndexedAccess.ts, 635, 62))
2313+
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 646, 30))
2314+
>dd : Symbol(dd, Decl(keyofAndIndexedAccess.ts, 646, 49))
2315+
>k1 : Symbol(k1, Decl(keyofAndIndexedAccess.ts, 646, 68))
2316+
2317+
return d[k2];
2318+
>d : Symbol(d, Decl(keyofAndIndexedAccess.ts, 647, 9))
2319+
>k2 : Symbol(k2, Decl(keyofAndIndexedAccess.ts, 646, 75))
2320+
}
2321+

tests/baselines/reference/keyofAndIndexedAccess.types

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2614,3 +2614,68 @@ declare function f7<K extends keyof I7>(type: K): Foo7<I7[K]>;
26142614
>I7 : I7
26152615
>K : K
26162616

2617+
// Repro from #21770
2618+
2619+
type Dict<T extends string> = { [key in T]: number };
2620+
>Dict : Dict<T>
2621+
>T : T
2622+
>key : key
2623+
>T : T
2624+
2625+
type DictDict<V extends string, T extends string> = { [key in V]: Dict<T> };
2626+
>DictDict : DictDict<V, T>
2627+
>V : V
2628+
>T : T
2629+
>key : key
2630+
>V : V
2631+
>Dict : Dict<T>
2632+
>T : T
2633+
2634+
function ff1<V extends string, T extends string>(dd: DictDict<V, T>, k1: V, k2: T): number {
2635+
>ff1 : <V extends string, T extends string>(dd: DictDict<V, T>, k1: V, k2: T) => number
2636+
>V : V
2637+
>T : T
2638+
>dd : DictDict<V, T>
2639+
>DictDict : DictDict<V, T>
2640+
>V : V
2641+
>T : T
2642+
>k1 : V
2643+
>V : V
2644+
>k2 : T
2645+
>T : T
2646+
2647+
return dd[k1][k2];
2648+
>dd[k1][k2] : DictDict<V, T>[V][T]
2649+
>dd[k1] : DictDict<V, T>[V]
2650+
>dd : DictDict<V, T>
2651+
>k1 : V
2652+
>k2 : T
2653+
}
2654+
2655+
function ff2<V extends string, T extends string>(dd: DictDict<V, T>, k1: V, k2: T): number {
2656+
>ff2 : <V extends string, T extends string>(dd: DictDict<V, T>, k1: V, k2: T) => number
2657+
>V : V
2658+
>T : T
2659+
>dd : DictDict<V, T>
2660+
>DictDict : DictDict<V, T>
2661+
>V : V
2662+
>T : T
2663+
>k1 : V
2664+
>V : V
2665+
>k2 : T
2666+
>T : T
2667+
2668+
const d: Dict<T> = dd[k1];
2669+
>d : Dict<T>
2670+
>Dict : Dict<T>
2671+
>T : T
2672+
>dd[k1] : DictDict<V, T>[V]
2673+
>dd : DictDict<V, T>
2674+
>k1 : V
2675+
2676+
return d[k2];
2677+
>d[k2] : Dict<T>[T]
2678+
>d : Dict<T>
2679+
>k2 : T
2680+
}
2681+

tests/cases/conformance/types/keyof/keyofAndIndexedAccess.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -637,3 +637,17 @@ interface I7 {
637637
}
638638
type Foo7<T extends number> = T;
639639
declare function f7<K extends keyof I7>(type: K): Foo7<I7[K]>;
640+
641+
// Repro from #21770
642+
643+
type Dict<T extends string> = { [key in T]: number };
644+
type DictDict<V extends string, T extends string> = { [key in V]: Dict<T> };
645+
646+
function ff1<V extends string, T extends string>(dd: DictDict<V, T>, k1: V, k2: T): number {
647+
return dd[k1][k2];
648+
}
649+
650+
function ff2<V extends string, T extends string>(dd: DictDict<V, T>, k1: V, k2: T): number {
651+
const d: Dict<T> = dd[k1];
652+
return d[k2];
653+
}

0 commit comments

Comments
 (0)