Skip to content

Commit c009620

Browse files
committed
Distribute index over mapped types when normalizing types
1 parent 01b1821 commit c009620

File tree

11 files changed

+699
-55
lines changed

11 files changed

+699
-55
lines changed

src/compiler/checker.ts

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17562,8 +17562,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1756217562
(type.flags & (TypeFlags.InstantiableNonPrimitive | TypeFlags.Index | TypeFlags.StringMapping) && !isPatternLiteralType(type) ? ObjectFlags.IsGenericIndexType : 0);
1756317563
}
1756417564

17565-
function getSimplifiedType(type: Type, writing: boolean): Type {
17566-
return type.flags & TypeFlags.IndexedAccess ? getSimplifiedIndexedAccessType(type as IndexedAccessType, writing) :
17565+
function getSimplifiedType(type: Type, writing: boolean, distributeIndexOverMappedType = false): Type {
17566+
return type.flags & TypeFlags.IndexedAccess ? getSimplifiedIndexedAccessType(type as IndexedAccessType, writing, distributeIndexOverMappedType) :
1756717567
type.flags & TypeFlags.Conditional ? getSimplifiedConditionalType(type as ConditionalType, writing) :
1756817568
type;
1756917569
}
@@ -17590,8 +17590,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1759017590
// Transform an indexed access to a simpler form, if possible. Return the simpler form, or return
1759117591
// the type itself if no transformation is possible. The writing flag indicates that the type is
1759217592
// the target of an assignment.
17593-
function getSimplifiedIndexedAccessType(type: IndexedAccessType, writing: boolean): Type {
17594-
const cache = writing ? "simplifiedForWriting" : "simplifiedForReading";
17593+
function getSimplifiedIndexedAccessType(type: IndexedAccessType, writing: boolean, distributeIndexOverMappedType: boolean): Type {
17594+
const cache = writing ? "simplifiedForWriting" : `simplifiedForReading${distributeIndexOverMappedType ? "D" : ""}` as const;
1759517595
if (type[cache]) {
1759617596
return type[cache] === circularConstraintType ? type : type[cache]!;
1759717597
}
@@ -17633,6 +17633,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1763317633
// For example, for an index access { [P in K]: Box<T[P]> }[X], we construct the type Box<T[X]>.
1763417634
if (isGenericMappedType(objectType)) {
1763517635
if (!getNameTypeFromMappedType(objectType) || isFilteringMappedType(objectType)) {
17636+
if (distributeIndexOverMappedType && !writing) {
17637+
const indexConstraint = indexType.flags & TypeFlags.Instantiable && getBaseConstraintOfType(indexType);
17638+
if (indexConstraint && indexConstraint.flags & TypeFlags.Union) {
17639+
return type[cache] = getSimplifiedType(getIndexedAccessType(objectType, getIntersectionType([indexType, indexConstraint])), writing);
17640+
}
17641+
}
17642+
1763617643
return type[cache] = mapType(substituteIndexedMappedType(objectType, type.indexType), t => getSimplifiedType(t, writing));
1763717644
}
1763817645
}
@@ -20263,7 +20270,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
2026320270
getObjectFlags(type) & ObjectFlags.Reference ? (type as TypeReference).node ? createTypeReference((type as TypeReference).target, getTypeArguments(type as TypeReference)) : getSingleBaseForNonAugmentingSubtype(type) || type :
2026420271
type.flags & TypeFlags.UnionOrIntersection ? getNormalizedUnionOrIntersectionType(type as UnionOrIntersectionType, writing) :
2026520272
type.flags & TypeFlags.Substitution ? writing ? (type as SubstitutionType).baseType : getSubstitutionIntersection(type as SubstitutionType) :
20266-
type.flags & TypeFlags.Simplifiable ? getSimplifiedType(type, writing) :
20273+
type.flags & TypeFlags.Simplifiable ? getSimplifiedType(type, writing, /*distributeIndexOverMappedType*/ true) :
2026720274
type;
2026820275
if (t === type) return t;
2026920276
type = t;

src/compiler/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6624,6 +6624,7 @@ export interface IndexedAccessType extends InstantiableType {
66246624
constraint?: Type;
66256625
simplifiedForReading?: Type;
66266626
simplifiedForWriting?: Type;
6627+
simplifiedForReadingD?: Type;
66276628
}
66286629

66296630
export type TypeVariable = TypeParameter | IndexedAccessType;

tests/baselines/reference/api/tsserverlibrary.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6983,6 +6983,7 @@ declare namespace ts {
69836983
constraint?: Type;
69846984
simplifiedForReading?: Type;
69856985
simplifiedForWriting?: Type;
6986+
simplifiedForReadingD?: Type;
69866987
}
69876988
type TypeVariable = TypeParameter | IndexedAccessType;
69886989
interface IndexType extends InstantiableType {

tests/baselines/reference/api/typescript.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2925,6 +2925,7 @@ declare namespace ts {
29252925
constraint?: Type;
29262926
simplifiedForReading?: Type;
29272927
simplifiedForWriting?: Type;
2928+
simplifiedForReadingD?: Type;
29282929
}
29292930
type TypeVariable = TypeParameter | IndexedAccessType;
29302931
interface IndexType extends InstantiableType {

tests/baselines/reference/conditionalTypes1.errors.txt

Lines changed: 26 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ conditionalTypes1.ts(17,5): error TS2322: Type 'T' is not assignable to type 'No
88
Type 'T' is not assignable to type '{}'.
99
Type 'string | undefined' is not assignable to type '{}'.
1010
Type 'undefined' is not assignable to type '{}'.
11-
conditionalTypes1.ts(24,5): error TS2322: Type 'T[keyof T] | undefined' is not assignable to type 'NonNullable<Partial<T>[keyof T]>'.
11+
conditionalTypes1.ts(24,5): error TS2322: Type 'T[keyof T & string] | T[keyof T & number] | T[keyof T & symbol] | undefined' is not assignable to type 'NonNullable<Partial<T>[keyof T]>'.
1212
Type 'undefined' is not assignable to type 'T[keyof T] & {}'.
1313
Type 'undefined' is not assignable to type 'T[keyof T]'.
1414
'T[keyof T]' could be instantiated with an arbitrary type which could be unrelated to 'undefined'.
@@ -25,32 +25,28 @@ conditionalTypes1.ts(104,5): error TS2322: Type 'NonFunctionProperties<T>' is no
2525
'T' could be instantiated with an arbitrary type which could be unrelated to 'NonFunctionProperties<T>'.
2626
conditionalTypes1.ts(106,5): error TS2322: Type 'NonFunctionProperties<T>' is not assignable to type 'FunctionProperties<T>'.
2727
Type 'FunctionPropertyNames<T>' is not assignable to type 'NonFunctionPropertyNames<T>'.
28-
Type 'keyof T' is not assignable to type 'T[keyof T] extends Function ? never : keyof T'.
29-
Type 'string | number | symbol' is not assignable to type 'T[keyof T] extends Function ? never : keyof T'.
30-
Type 'string' is not assignable to type 'T[keyof T] extends Function ? never : keyof T'.
31-
Type 'keyof T' is not assignable to type 'never'.
32-
Type 'string | number | symbol' is not assignable to type 'never'.
33-
Type 'string' is not assignable to type 'never'.
28+
Type 'T[keyof T & string] extends Function ? keyof T & string : never' is not assignable to type 'T[keyof T] extends Function ? never : keyof T'.
29+
Type 'keyof T & string' is not assignable to type 'T[keyof T] extends Function ? never : keyof T'.
30+
Type 'keyof T & string' is not assignable to type 'never'.
3431
conditionalTypes1.ts(108,5): error TS2322: Type 'FunctionProperties<T>' is not assignable to type 'NonFunctionProperties<T>'.
3532
Type 'NonFunctionPropertyNames<T>' is not assignable to type 'FunctionPropertyNames<T>'.
36-
Type 'keyof T' is not assignable to type 'T[keyof T] extends Function ? keyof T : never'.
37-
Type 'string | number | symbol' is not assignable to type 'T[keyof T] extends Function ? keyof T : never'.
38-
Type 'string' is not assignable to type 'T[keyof T] extends Function ? keyof T : never'.
39-
Type 'keyof T' is not assignable to type 'never'.
33+
Type 'T[keyof T & string] extends Function ? never : keyof T & string' is not assignable to type 'T[keyof T] extends Function ? keyof T : never'.
34+
Type 'keyof T & string' is not assignable to type 'T[keyof T] extends Function ? keyof T : never'.
35+
Type 'keyof T & string' is not assignable to type 'never'.
4036
conditionalTypes1.ts(114,5): error TS2322: Type 'keyof T' is not assignable to type 'FunctionPropertyNames<T>'.
4137
Type 'string | number | symbol' is not assignable to type 'T[keyof T] extends Function ? keyof T : never'.
4238
Type 'string' is not assignable to type 'T[keyof T] extends Function ? keyof T : never'.
4339
conditionalTypes1.ts(115,5): error TS2322: Type 'NonFunctionPropertyNames<T>' is not assignable to type 'FunctionPropertyNames<T>'.
44-
Type 'keyof T' is not assignable to type 'T[keyof T] extends Function ? keyof T : never'.
45-
Type 'keyof T' is not assignable to type 'never'.
46-
Type 'string | number | symbol' is not assignable to type 'never'.
47-
Type 'string' is not assignable to type 'never'.
40+
Type 'T[keyof T & string] extends Function ? never : keyof T & string' is not assignable to type 'T[keyof T] extends Function ? keyof T : never'.
41+
Type 'keyof T & string' is not assignable to type 'T[keyof T] extends Function ? keyof T : never'.
42+
Type 'keyof T & string' is not assignable to type 'never'.
4843
conditionalTypes1.ts(116,5): error TS2322: Type 'keyof T' is not assignable to type 'NonFunctionPropertyNames<T>'.
4944
Type 'string | number | symbol' is not assignable to type 'T[keyof T] extends Function ? never : keyof T'.
5045
Type 'string' is not assignable to type 'T[keyof T] extends Function ? never : keyof T'.
5146
conditionalTypes1.ts(117,5): error TS2322: Type 'FunctionPropertyNames<T>' is not assignable to type 'NonFunctionPropertyNames<T>'.
52-
Type 'keyof T' is not assignable to type 'T[keyof T] extends Function ? never : keyof T'.
53-
Type 'keyof T' is not assignable to type 'never'.
47+
Type 'T[keyof T & string] extends Function ? keyof T & string : never' is not assignable to type 'T[keyof T] extends Function ? never : keyof T'.
48+
Type 'keyof T & string' is not assignable to type 'T[keyof T] extends Function ? never : keyof T'.
49+
Type 'keyof T & string' is not assignable to type 'never'.
5450
conditionalTypes1.ts(134,10): error TS2540: Cannot assign to 'id' because it is a read-only property.
5551
conditionalTypes1.ts(135,5): error TS2542: Index signature in type 'DeepReadonlyArray<Part>' only permits reading.
5652
conditionalTypes1.ts(136,22): error TS2540: Cannot assign to 'id' because it is a read-only property.
@@ -108,7 +104,7 @@ conditionalTypes1.ts(288,43): error TS2322: Type 'T95<U>' is not assignable to t
108104
x = y;
109105
y = x; // Error
110106
~
111-
!!! error TS2322: Type 'T[keyof T] | undefined' is not assignable to type 'NonNullable<Partial<T>[keyof T]>'.
107+
!!! error TS2322: Type 'T[keyof T & string] | T[keyof T & number] | T[keyof T & symbol] | undefined' is not assignable to type 'NonNullable<Partial<T>[keyof T]>'.
112108
!!! error TS2322: Type 'undefined' is not assignable to type 'T[keyof T] & {}'.
113109
!!! error TS2322: Type 'undefined' is not assignable to type 'T[keyof T]'.
114110
!!! error TS2322: 'T[keyof T]' could be instantiated with an arbitrary type which could be unrelated to 'undefined'.
@@ -211,21 +207,17 @@ conditionalTypes1.ts(288,43): error TS2322: Type 'T95<U>' is not assignable to t
211207
~
212208
!!! error TS2322: Type 'NonFunctionProperties<T>' is not assignable to type 'FunctionProperties<T>'.
213209
!!! error TS2322: Type 'FunctionPropertyNames<T>' is not assignable to type 'NonFunctionPropertyNames<T>'.
214-
!!! error TS2322: Type 'keyof T' is not assignable to type 'T[keyof T] extends Function ? never : keyof T'.
215-
!!! error TS2322: Type 'string | number | symbol' is not assignable to type 'T[keyof T] extends Function ? never : keyof T'.
216-
!!! error TS2322: Type 'string' is not assignable to type 'T[keyof T] extends Function ? never : keyof T'.
217-
!!! error TS2322: Type 'keyof T' is not assignable to type 'never'.
218-
!!! error TS2322: Type 'string | number | symbol' is not assignable to type 'never'.
219-
!!! error TS2322: Type 'string' is not assignable to type 'never'.
210+
!!! error TS2322: Type 'T[keyof T & string] extends Function ? keyof T & string : never' is not assignable to type 'T[keyof T] extends Function ? never : keyof T'.
211+
!!! error TS2322: Type 'keyof T & string' is not assignable to type 'T[keyof T] extends Function ? never : keyof T'.
212+
!!! error TS2322: Type 'keyof T & string' is not assignable to type 'never'.
220213
z = x;
221214
z = y; // Error
222215
~
223216
!!! error TS2322: Type 'FunctionProperties<T>' is not assignable to type 'NonFunctionProperties<T>'.
224217
!!! error TS2322: Type 'NonFunctionPropertyNames<T>' is not assignable to type 'FunctionPropertyNames<T>'.
225-
!!! error TS2322: Type 'keyof T' is not assignable to type 'T[keyof T] extends Function ? keyof T : never'.
226-
!!! error TS2322: Type 'string | number | symbol' is not assignable to type 'T[keyof T] extends Function ? keyof T : never'.
227-
!!! error TS2322: Type 'string' is not assignable to type 'T[keyof T] extends Function ? keyof T : never'.
228-
!!! error TS2322: Type 'keyof T' is not assignable to type 'never'.
218+
!!! error TS2322: Type 'T[keyof T & string] extends Function ? never : keyof T & string' is not assignable to type 'T[keyof T] extends Function ? keyof T : never'.
219+
!!! error TS2322: Type 'keyof T & string' is not assignable to type 'T[keyof T] extends Function ? keyof T : never'.
220+
!!! error TS2322: Type 'keyof T & string' is not assignable to type 'never'.
229221
}
230222

231223
function f8<T>(x: keyof T, y: FunctionPropertyNames<T>, z: NonFunctionPropertyNames<T>) {
@@ -239,10 +231,9 @@ conditionalTypes1.ts(288,43): error TS2322: Type 'T95<U>' is not assignable to t
239231
y = z; // Error
240232
~
241233
!!! error TS2322: Type 'NonFunctionPropertyNames<T>' is not assignable to type 'FunctionPropertyNames<T>'.
242-
!!! error TS2322: Type 'keyof T' is not assignable to type 'T[keyof T] extends Function ? keyof T : never'.
243-
!!! error TS2322: Type 'keyof T' is not assignable to type 'never'.
244-
!!! error TS2322: Type 'string | number | symbol' is not assignable to type 'never'.
245-
!!! error TS2322: Type 'string' is not assignable to type 'never'.
234+
!!! error TS2322: Type 'T[keyof T & string] extends Function ? never : keyof T & string' is not assignable to type 'T[keyof T] extends Function ? keyof T : never'.
235+
!!! error TS2322: Type 'keyof T & string' is not assignable to type 'T[keyof T] extends Function ? keyof T : never'.
236+
!!! error TS2322: Type 'keyof T & string' is not assignable to type 'never'.
246237
z = x; // Error
247238
~
248239
!!! error TS2322: Type 'keyof T' is not assignable to type 'NonFunctionPropertyNames<T>'.
@@ -251,8 +242,9 @@ conditionalTypes1.ts(288,43): error TS2322: Type 'T95<U>' is not assignable to t
251242
z = y; // Error
252243
~
253244
!!! error TS2322: Type 'FunctionPropertyNames<T>' is not assignable to type 'NonFunctionPropertyNames<T>'.
254-
!!! error TS2322: Type 'keyof T' is not assignable to type 'T[keyof T] extends Function ? never : keyof T'.
255-
!!! error TS2322: Type 'keyof T' is not assignable to type 'never'.
245+
!!! error TS2322: Type 'T[keyof T & string] extends Function ? keyof T & string : never' is not assignable to type 'T[keyof T] extends Function ? never : keyof T'.
246+
!!! error TS2322: Type 'keyof T & string' is not assignable to type 'T[keyof T] extends Function ? never : keyof T'.
247+
!!! error TS2322: Type 'keyof T & string' is not assignable to type 'never'.
256248
}
257249

258250
type DeepReadonly<T> =

0 commit comments

Comments
 (0)