Skip to content

Commit 277732e

Browse files
committed
Accurate constraintType for indexedAccessType
1 parent c6fb2e1 commit 277732e

9 files changed

+328
-67
lines changed

src/compiler/checker.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13508,7 +13508,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1350813508
// we substitute an instantiation of E where P is replaced with X.
1350913509
return substituteIndexedMappedType(type.objectType as MappedType, type.indexType);
1351013510
}
13511-
const indexConstraint = getSimplifiedTypeOrConstraint(type.indexType);
13511+
const indexType = type.indexType;
13512+
let indexConstraint = getSimplifiedTypeOrConstraint(indexType);
13513+
if (indexConstraint && indexConstraint.flags & TypeFlags.Index) {
13514+
const constraint = getBaseConstraintOfType((indexConstraint as IndexType).type);
13515+
indexConstraint = constraint && constraint !== noConstraintType ?getIndexType(constraint): keyofConstraintType;
13516+
}
1351213517
if (indexConstraint && indexConstraint !== type.indexType) {
1351313518
const indexedAccess = getIndexedAccessTypeOrUndefined(type.objectType, indexConstraint, type.accessFlags);
1351413519
if (indexedAccess) {
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
//// [constraintWithIndexedAccess.ts]
2+
// #52399
3+
type DataFetchFns = {
4+
Boat: {
5+
requiresLicense: (id: string) => boolean;
6+
maxGroundSpeed: (id: string) => number;
7+
description: (id: string) => string;
8+
displacement: (id: string) => number;
9+
name: (id: string) => string;
10+
};
11+
Plane: {
12+
requiresLicense: (id: string) => boolean;
13+
maxGroundSpeed: (id: string) => number;
14+
maxTakeoffWeight: (id: string) => number;
15+
maxCruisingAltitude: (id: string) => number;
16+
name: (id: string) => string;
17+
}
18+
}
19+
export type NoTypeParamBoatRequired<F extends keyof DataFetchFns['Boat']> = ReturnType<DataFetchFns['Boat'][F]>;
20+
type TypeHardcodedAsParameterWithoutReturnType<T extends 'Boat', F extends keyof DataFetchFns[T]> = DataFetchFns[T][F];
21+
export type allAreFunctionsAsExpected = TypeHardcodedAsParameterWithoutReturnType<'Boat', keyof DataFetchFns['Boat']>;
22+
export type returnTypeOfFunctions = ReturnType<allAreFunctionsAsExpected>; //string | number | boolean as expected
23+
export type SucceedingCombo = ReturnType<TypeHardcodedAsParameterWithoutReturnType<'Boat', keyof DataFetchFns['Boat']>>;
24+
export type FailingCombo<T extends 'Boat', F extends keyof DataFetchFns[T]> = ReturnType<TypeHardcodedAsParameterWithoutReturnType<T,F>>;
25+
export type TypeHardcodedAsParameter<T extends 'Boat', F extends keyof DataFetchFns[T]> = ReturnType<DataFetchFns[T][F]>;
26+
type VehicleSelector<T extends keyof DataFetchFns> = DataFetchFns[T];
27+
export type TypeHardcodedAsParameter2<T extends 'Boat', F extends keyof DataFetchFns[T]> = ReturnType<VehicleSelector<T>[F]>;
28+
export type TypeGeneric<T extends keyof DataFetchFns, F extends keyof DataFetchFns[T]> = ReturnType<DataFetchFns[T][F]>;
29+
30+
31+
//// [constraintWithIndexedAccess.js]
32+
"use strict";
33+
Object.defineProperty(exports, "__esModule", { value: true });
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
=== tests/cases/compiler/constraintWithIndexedAccess.ts ===
2+
// #52399
3+
type DataFetchFns = {
4+
>DataFetchFns : Symbol(DataFetchFns, Decl(constraintWithIndexedAccess.ts, 0, 0))
5+
6+
Boat: {
7+
>Boat : Symbol(Boat, Decl(constraintWithIndexedAccess.ts, 1, 21))
8+
9+
requiresLicense: (id: string) => boolean;
10+
>requiresLicense : Symbol(requiresLicense, Decl(constraintWithIndexedAccess.ts, 2, 11))
11+
>id : Symbol(id, Decl(constraintWithIndexedAccess.ts, 3, 26))
12+
13+
maxGroundSpeed: (id: string) => number;
14+
>maxGroundSpeed : Symbol(maxGroundSpeed, Decl(constraintWithIndexedAccess.ts, 3, 49))
15+
>id : Symbol(id, Decl(constraintWithIndexedAccess.ts, 4, 25))
16+
17+
description: (id: string) => string;
18+
>description : Symbol(description, Decl(constraintWithIndexedAccess.ts, 4, 47))
19+
>id : Symbol(id, Decl(constraintWithIndexedAccess.ts, 5, 22))
20+
21+
displacement: (id: string) => number;
22+
>displacement : Symbol(displacement, Decl(constraintWithIndexedAccess.ts, 5, 44))
23+
>id : Symbol(id, Decl(constraintWithIndexedAccess.ts, 6, 23))
24+
25+
name: (id: string) => string;
26+
>name : Symbol(name, Decl(constraintWithIndexedAccess.ts, 6, 45))
27+
>id : Symbol(id, Decl(constraintWithIndexedAccess.ts, 7, 15))
28+
29+
};
30+
Plane: {
31+
>Plane : Symbol(Plane, Decl(constraintWithIndexedAccess.ts, 8, 6))
32+
33+
requiresLicense: (id: string) => boolean;
34+
>requiresLicense : Symbol(requiresLicense, Decl(constraintWithIndexedAccess.ts, 9, 12))
35+
>id : Symbol(id, Decl(constraintWithIndexedAccess.ts, 10, 26))
36+
37+
maxGroundSpeed: (id: string) => number;
38+
>maxGroundSpeed : Symbol(maxGroundSpeed, Decl(constraintWithIndexedAccess.ts, 10, 49))
39+
>id : Symbol(id, Decl(constraintWithIndexedAccess.ts, 11, 25))
40+
41+
maxTakeoffWeight: (id: string) => number;
42+
>maxTakeoffWeight : Symbol(maxTakeoffWeight, Decl(constraintWithIndexedAccess.ts, 11, 47))
43+
>id : Symbol(id, Decl(constraintWithIndexedAccess.ts, 12, 27))
44+
45+
maxCruisingAltitude: (id: string) => number;
46+
>maxCruisingAltitude : Symbol(maxCruisingAltitude, Decl(constraintWithIndexedAccess.ts, 12, 49))
47+
>id : Symbol(id, Decl(constraintWithIndexedAccess.ts, 13, 30))
48+
49+
name: (id: string) => string;
50+
>name : Symbol(name, Decl(constraintWithIndexedAccess.ts, 13, 52))
51+
>id : Symbol(id, Decl(constraintWithIndexedAccess.ts, 14, 15))
52+
}
53+
}
54+
export type NoTypeParamBoatRequired<F extends keyof DataFetchFns['Boat']> = ReturnType<DataFetchFns['Boat'][F]>;
55+
>NoTypeParamBoatRequired : Symbol(NoTypeParamBoatRequired, Decl(constraintWithIndexedAccess.ts, 16, 1))
56+
>F : Symbol(F, Decl(constraintWithIndexedAccess.ts, 17, 36))
57+
>DataFetchFns : Symbol(DataFetchFns, Decl(constraintWithIndexedAccess.ts, 0, 0))
58+
>ReturnType : Symbol(ReturnType, Decl(lib.es5.d.ts, --, --))
59+
>DataFetchFns : Symbol(DataFetchFns, Decl(constraintWithIndexedAccess.ts, 0, 0))
60+
>F : Symbol(F, Decl(constraintWithIndexedAccess.ts, 17, 36))
61+
62+
type TypeHardcodedAsParameterWithoutReturnType<T extends 'Boat', F extends keyof DataFetchFns[T]> = DataFetchFns[T][F];
63+
>TypeHardcodedAsParameterWithoutReturnType : Symbol(TypeHardcodedAsParameterWithoutReturnType, Decl(constraintWithIndexedAccess.ts, 17, 112))
64+
>T : Symbol(T, Decl(constraintWithIndexedAccess.ts, 18, 47))
65+
>F : Symbol(F, Decl(constraintWithIndexedAccess.ts, 18, 64))
66+
>DataFetchFns : Symbol(DataFetchFns, Decl(constraintWithIndexedAccess.ts, 0, 0))
67+
>T : Symbol(T, Decl(constraintWithIndexedAccess.ts, 18, 47))
68+
>DataFetchFns : Symbol(DataFetchFns, Decl(constraintWithIndexedAccess.ts, 0, 0))
69+
>T : Symbol(T, Decl(constraintWithIndexedAccess.ts, 18, 47))
70+
>F : Symbol(F, Decl(constraintWithIndexedAccess.ts, 18, 64))
71+
72+
export type allAreFunctionsAsExpected = TypeHardcodedAsParameterWithoutReturnType<'Boat', keyof DataFetchFns['Boat']>;
73+
>allAreFunctionsAsExpected : Symbol(allAreFunctionsAsExpected, Decl(constraintWithIndexedAccess.ts, 18, 119))
74+
>TypeHardcodedAsParameterWithoutReturnType : Symbol(TypeHardcodedAsParameterWithoutReturnType, Decl(constraintWithIndexedAccess.ts, 17, 112))
75+
>DataFetchFns : Symbol(DataFetchFns, Decl(constraintWithIndexedAccess.ts, 0, 0))
76+
77+
export type returnTypeOfFunctions = ReturnType<allAreFunctionsAsExpected>; //string | number | boolean as expected
78+
>returnTypeOfFunctions : Symbol(returnTypeOfFunctions, Decl(constraintWithIndexedAccess.ts, 19, 118))
79+
>ReturnType : Symbol(ReturnType, Decl(lib.es5.d.ts, --, --))
80+
>allAreFunctionsAsExpected : Symbol(allAreFunctionsAsExpected, Decl(constraintWithIndexedAccess.ts, 18, 119))
81+
82+
export type SucceedingCombo = ReturnType<TypeHardcodedAsParameterWithoutReturnType<'Boat', keyof DataFetchFns['Boat']>>;
83+
>SucceedingCombo : Symbol(SucceedingCombo, Decl(constraintWithIndexedAccess.ts, 20, 74))
84+
>ReturnType : Symbol(ReturnType, Decl(lib.es5.d.ts, --, --))
85+
>TypeHardcodedAsParameterWithoutReturnType : Symbol(TypeHardcodedAsParameterWithoutReturnType, Decl(constraintWithIndexedAccess.ts, 17, 112))
86+
>DataFetchFns : Symbol(DataFetchFns, Decl(constraintWithIndexedAccess.ts, 0, 0))
87+
88+
export type FailingCombo<T extends 'Boat', F extends keyof DataFetchFns[T]> = ReturnType<TypeHardcodedAsParameterWithoutReturnType<T,F>>;
89+
>FailingCombo : Symbol(FailingCombo, Decl(constraintWithIndexedAccess.ts, 21, 120))
90+
>T : Symbol(T, Decl(constraintWithIndexedAccess.ts, 22, 25))
91+
>F : Symbol(F, Decl(constraintWithIndexedAccess.ts, 22, 42))
92+
>DataFetchFns : Symbol(DataFetchFns, Decl(constraintWithIndexedAccess.ts, 0, 0))
93+
>T : Symbol(T, Decl(constraintWithIndexedAccess.ts, 22, 25))
94+
>ReturnType : Symbol(ReturnType, Decl(lib.es5.d.ts, --, --))
95+
>TypeHardcodedAsParameterWithoutReturnType : Symbol(TypeHardcodedAsParameterWithoutReturnType, Decl(constraintWithIndexedAccess.ts, 17, 112))
96+
>T : Symbol(T, Decl(constraintWithIndexedAccess.ts, 22, 25))
97+
>F : Symbol(F, Decl(constraintWithIndexedAccess.ts, 22, 42))
98+
99+
export type TypeHardcodedAsParameter<T extends 'Boat', F extends keyof DataFetchFns[T]> = ReturnType<DataFetchFns[T][F]>;
100+
>TypeHardcodedAsParameter : Symbol(TypeHardcodedAsParameter, Decl(constraintWithIndexedAccess.ts, 22, 137))
101+
>T : Symbol(T, Decl(constraintWithIndexedAccess.ts, 23, 37))
102+
>F : Symbol(F, Decl(constraintWithIndexedAccess.ts, 23, 54))
103+
>DataFetchFns : Symbol(DataFetchFns, Decl(constraintWithIndexedAccess.ts, 0, 0))
104+
>T : Symbol(T, Decl(constraintWithIndexedAccess.ts, 23, 37))
105+
>ReturnType : Symbol(ReturnType, Decl(lib.es5.d.ts, --, --))
106+
>DataFetchFns : Symbol(DataFetchFns, Decl(constraintWithIndexedAccess.ts, 0, 0))
107+
>T : Symbol(T, Decl(constraintWithIndexedAccess.ts, 23, 37))
108+
>F : Symbol(F, Decl(constraintWithIndexedAccess.ts, 23, 54))
109+
110+
type VehicleSelector<T extends keyof DataFetchFns> = DataFetchFns[T];
111+
>VehicleSelector : Symbol(VehicleSelector, Decl(constraintWithIndexedAccess.ts, 23, 121))
112+
>T : Symbol(T, Decl(constraintWithIndexedAccess.ts, 24, 21))
113+
>DataFetchFns : Symbol(DataFetchFns, Decl(constraintWithIndexedAccess.ts, 0, 0))
114+
>DataFetchFns : Symbol(DataFetchFns, Decl(constraintWithIndexedAccess.ts, 0, 0))
115+
>T : Symbol(T, Decl(constraintWithIndexedAccess.ts, 24, 21))
116+
117+
export type TypeHardcodedAsParameter2<T extends 'Boat', F extends keyof DataFetchFns[T]> = ReturnType<VehicleSelector<T>[F]>;
118+
>TypeHardcodedAsParameter2 : Symbol(TypeHardcodedAsParameter2, Decl(constraintWithIndexedAccess.ts, 24, 69))
119+
>T : Symbol(T, Decl(constraintWithIndexedAccess.ts, 25, 38))
120+
>F : Symbol(F, Decl(constraintWithIndexedAccess.ts, 25, 55))
121+
>DataFetchFns : Symbol(DataFetchFns, Decl(constraintWithIndexedAccess.ts, 0, 0))
122+
>T : Symbol(T, Decl(constraintWithIndexedAccess.ts, 25, 38))
123+
>ReturnType : Symbol(ReturnType, Decl(lib.es5.d.ts, --, --))
124+
>VehicleSelector : Symbol(VehicleSelector, Decl(constraintWithIndexedAccess.ts, 23, 121))
125+
>T : Symbol(T, Decl(constraintWithIndexedAccess.ts, 25, 38))
126+
>F : Symbol(F, Decl(constraintWithIndexedAccess.ts, 25, 55))
127+
128+
export type TypeGeneric<T extends keyof DataFetchFns, F extends keyof DataFetchFns[T]> = ReturnType<DataFetchFns[T][F]>;
129+
>TypeGeneric : Symbol(TypeGeneric, Decl(constraintWithIndexedAccess.ts, 25, 125))
130+
>T : Symbol(T, Decl(constraintWithIndexedAccess.ts, 26, 24))
131+
>DataFetchFns : Symbol(DataFetchFns, Decl(constraintWithIndexedAccess.ts, 0, 0))
132+
>F : Symbol(F, Decl(constraintWithIndexedAccess.ts, 26, 53))
133+
>DataFetchFns : Symbol(DataFetchFns, Decl(constraintWithIndexedAccess.ts, 0, 0))
134+
>T : Symbol(T, Decl(constraintWithIndexedAccess.ts, 26, 24))
135+
>ReturnType : Symbol(ReturnType, Decl(lib.es5.d.ts, --, --))
136+
>DataFetchFns : Symbol(DataFetchFns, Decl(constraintWithIndexedAccess.ts, 0, 0))
137+
>T : Symbol(T, Decl(constraintWithIndexedAccess.ts, 26, 24))
138+
>F : Symbol(F, Decl(constraintWithIndexedAccess.ts, 26, 53))
139+
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
=== tests/cases/compiler/constraintWithIndexedAccess.ts ===
2+
// #52399
3+
type DataFetchFns = {
4+
>DataFetchFns : { Boat: { requiresLicense: (id: string) => boolean; maxGroundSpeed: (id: string) => number; description: (id: string) => string; displacement: (id: string) => number; name: (id: string) => string; }; Plane: { requiresLicense: (id: string) => boolean; maxGroundSpeed: (id: string) => number; maxTakeoffWeight: (id: string) => number; maxCruisingAltitude: (id: string) => number; name: (id: string) => string; }; }
5+
6+
Boat: {
7+
>Boat : { requiresLicense: (id: string) => boolean; maxGroundSpeed: (id: string) => number; description: (id: string) => string; displacement: (id: string) => number; name: (id: string) => string; }
8+
9+
requiresLicense: (id: string) => boolean;
10+
>requiresLicense : (id: string) => boolean
11+
>id : string
12+
13+
maxGroundSpeed: (id: string) => number;
14+
>maxGroundSpeed : (id: string) => number
15+
>id : string
16+
17+
description: (id: string) => string;
18+
>description : (id: string) => string
19+
>id : string
20+
21+
displacement: (id: string) => number;
22+
>displacement : (id: string) => number
23+
>id : string
24+
25+
name: (id: string) => string;
26+
>name : (id: string) => string
27+
>id : string
28+
29+
};
30+
Plane: {
31+
>Plane : { requiresLicense: (id: string) => boolean; maxGroundSpeed: (id: string) => number; maxTakeoffWeight: (id: string) => number; maxCruisingAltitude: (id: string) => number; name: (id: string) => string; }
32+
33+
requiresLicense: (id: string) => boolean;
34+
>requiresLicense : (id: string) => boolean
35+
>id : string
36+
37+
maxGroundSpeed: (id: string) => number;
38+
>maxGroundSpeed : (id: string) => number
39+
>id : string
40+
41+
maxTakeoffWeight: (id: string) => number;
42+
>maxTakeoffWeight : (id: string) => number
43+
>id : string
44+
45+
maxCruisingAltitude: (id: string) => number;
46+
>maxCruisingAltitude : (id: string) => number
47+
>id : string
48+
49+
name: (id: string) => string;
50+
>name : (id: string) => string
51+
>id : string
52+
}
53+
}
54+
export type NoTypeParamBoatRequired<F extends keyof DataFetchFns['Boat']> = ReturnType<DataFetchFns['Boat'][F]>;
55+
>NoTypeParamBoatRequired : NoTypeParamBoatRequired<F>
56+
57+
type TypeHardcodedAsParameterWithoutReturnType<T extends 'Boat', F extends keyof DataFetchFns[T]> = DataFetchFns[T][F];
58+
>TypeHardcodedAsParameterWithoutReturnType : TypeHardcodedAsParameterWithoutReturnType<T, F>
59+
60+
export type allAreFunctionsAsExpected = TypeHardcodedAsParameterWithoutReturnType<'Boat', keyof DataFetchFns['Boat']>;
61+
>allAreFunctionsAsExpected : ((id: string) => boolean) | ((id: string) => number) | ((id: string) => string) | ((id: string) => number) | ((id: string) => string)
62+
63+
export type returnTypeOfFunctions = ReturnType<allAreFunctionsAsExpected>; //string | number | boolean as expected
64+
>returnTypeOfFunctions : string | number | boolean
65+
66+
export type SucceedingCombo = ReturnType<TypeHardcodedAsParameterWithoutReturnType<'Boat', keyof DataFetchFns['Boat']>>;
67+
>SucceedingCombo : string | number | boolean
68+
69+
export type FailingCombo<T extends 'Boat', F extends keyof DataFetchFns[T]> = ReturnType<TypeHardcodedAsParameterWithoutReturnType<T,F>>;
70+
>FailingCombo : FailingCombo<T, F>
71+
72+
export type TypeHardcodedAsParameter<T extends 'Boat', F extends keyof DataFetchFns[T]> = ReturnType<DataFetchFns[T][F]>;
73+
>TypeHardcodedAsParameter : TypeHardcodedAsParameter<T, F>
74+
75+
type VehicleSelector<T extends keyof DataFetchFns> = DataFetchFns[T];
76+
>VehicleSelector : VehicleSelector<T>
77+
78+
export type TypeHardcodedAsParameter2<T extends 'Boat', F extends keyof DataFetchFns[T]> = ReturnType<VehicleSelector<T>[F]>;
79+
>TypeHardcodedAsParameter2 : TypeHardcodedAsParameter2<T, F>
80+
81+
export type TypeGeneric<T extends keyof DataFetchFns, F extends keyof DataFetchFns[T]> = ReturnType<DataFetchFns[T][F]>;
82+
>TypeGeneric : TypeGeneric<T, F>
83+

tests/baselines/reference/deepComparisons.errors.txt

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,12 @@
11
tests/cases/compiler/deepComparisons.ts(2,9): error TS2322: Type 'T' is not assignable to type 'Extract<T, string>'.
22
tests/cases/compiler/deepComparisons.ts(3,9): error TS2322: Type 'T[K1]' is not assignable to type 'Extract<T[K1], string>'.
3-
Type 'T[keyof T]' is not assignable to type 'Extract<T[K1], string>'.
4-
Type 'T[string] | T[number] | T[symbol]' is not assignable to type 'Extract<T[K1], string>'.
5-
Type 'T[string]' is not assignable to type 'Extract<T[K1], string>'.
3+
Type 'T[string] | T[number] | T[symbol]' is not assignable to type 'Extract<T[K1], string>'.
4+
Type 'T[string]' is not assignable to type 'Extract<T[K1], string>'.
65
tests/cases/compiler/deepComparisons.ts(4,9): error TS2322: Type 'T[K1][K2]' is not assignable to type 'Extract<T[K1][K2], string>'.
7-
Type 'T[K1][keyof T[K1]]' is not assignable to type 'Extract<T[K1][K2], string>'.
8-
Type 'T[K1][string] | T[K1][number] | T[K1][symbol]' is not assignable to type 'Extract<T[K1][K2], string>'.
9-
Type 'T[K1][string]' is not assignable to type 'Extract<T[K1][K2], string>'.
10-
Type 'T[keyof T][string]' is not assignable to type 'Extract<T[K1][K2], string>'.
11-
Type 'T[string][string] | T[number][string] | T[symbol][string]' is not assignable to type 'Extract<T[K1][K2], string>'.
12-
Type 'T[string][string]' is not assignable to type 'Extract<T[K1][K2], string>'.
6+
Type 'T[K1][string] | T[K1][number] | T[K1][symbol]' is not assignable to type 'Extract<T[K1][K2], string>'.
7+
Type 'T[K1][string]' is not assignable to type 'Extract<T[K1][K2], string>'.
8+
Type 'T[string][string] | T[number][string] | T[symbol][string]' is not assignable to type 'Extract<T[K1][K2], string>'.
9+
Type 'T[string][string]' is not assignable to type 'Extract<T[K1][K2], string>'.
1310

1411

1512
==== tests/cases/compiler/deepComparisons.ts (3 errors) ====
@@ -20,18 +17,15 @@ tests/cases/compiler/deepComparisons.ts(4,9): error TS2322: Type 'T[K1][K2]' is
2017
let v2: Extract<T[K1], string> = 0 as any as T[K1]; // Error
2118
~~
2219
!!! error TS2322: Type 'T[K1]' is not assignable to type 'Extract<T[K1], string>'.
23-
!!! error TS2322: Type 'T[keyof T]' is not assignable to type 'Extract<T[K1], string>'.
24-
!!! error TS2322: Type 'T[string] | T[number] | T[symbol]' is not assignable to type 'Extract<T[K1], string>'.
25-
!!! error TS2322: Type 'T[string]' is not assignable to type 'Extract<T[K1], string>'.
20+
!!! error TS2322: Type 'T[string] | T[number] | T[symbol]' is not assignable to type 'Extract<T[K1], string>'.
21+
!!! error TS2322: Type 'T[string]' is not assignable to type 'Extract<T[K1], string>'.
2622
let v3: Extract<T[K1][K2], string> = 0 as any as T[K1][K2]; // No error
2723
~~
2824
!!! error TS2322: Type 'T[K1][K2]' is not assignable to type 'Extract<T[K1][K2], string>'.
29-
!!! error TS2322: Type 'T[K1][keyof T[K1]]' is not assignable to type 'Extract<T[K1][K2], string>'.
30-
!!! error TS2322: Type 'T[K1][string] | T[K1][number] | T[K1][symbol]' is not assignable to type 'Extract<T[K1][K2], string>'.
31-
!!! error TS2322: Type 'T[K1][string]' is not assignable to type 'Extract<T[K1][K2], string>'.
32-
!!! error TS2322: Type 'T[keyof T][string]' is not assignable to type 'Extract<T[K1][K2], string>'.
33-
!!! error TS2322: Type 'T[string][string] | T[number][string] | T[symbol][string]' is not assignable to type 'Extract<T[K1][K2], string>'.
34-
!!! error TS2322: Type 'T[string][string]' is not assignable to type 'Extract<T[K1][K2], string>'.
25+
!!! error TS2322: Type 'T[K1][string] | T[K1][number] | T[K1][symbol]' is not assignable to type 'Extract<T[K1][K2], string>'.
26+
!!! error TS2322: Type 'T[K1][string]' is not assignable to type 'Extract<T[K1][K2], string>'.
27+
!!! error TS2322: Type 'T[string][string] | T[number][string] | T[symbol][string]' is not assignable to type 'Extract<T[K1][K2], string>'.
28+
!!! error TS2322: Type 'T[string][string]' is not assignable to type 'Extract<T[K1][K2], string>'.
3529
}
3630

3731
type Foo<T> = { x: Foo<T> };

0 commit comments

Comments
 (0)