@@ -1304,6 +1304,12 @@ const enum MappedTypeModifiers {
1304
1304
ExcludeOptional = 1 << 3,
1305
1305
}
1306
1306
1307
+ const enum MappedTypeNameTypeKind {
1308
+ None,
1309
+ Filtering,
1310
+ Remapping,
1311
+ }
1312
+
1307
1313
const enum ExpandingFlags {
1308
1314
None = 0,
1309
1315
Source = 1,
@@ -13741,7 +13747,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
13741
13747
const constraintType = getConstraintTypeFromMappedType(type);
13742
13748
const mappedType = (type.target as MappedType) || type;
13743
13749
const nameType = getNameTypeFromMappedType(mappedType);
13744
- const shouldLinkPropDeclarations = !nameType || isFilteringMappedType (mappedType);
13750
+ const shouldLinkPropDeclarations = getMappedTypeNameTypeKind (mappedType) !== MappedTypeNameTypeKind.Remapping ;
13745
13751
const templateType = getTemplateTypeFromMappedType(mappedType);
13746
13752
const modifiersType = getApparentType(getModifiersTypeFromMappedType(type)); // The 'T' in 'keyof T'
13747
13753
const templateModifiers = getMappedTypeModifiers(type);
@@ -13923,9 +13929,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
13923
13929
return false;
13924
13930
}
13925
13931
13926
- function isFilteringMappedType (type: MappedType): boolean {
13932
+ function getMappedTypeNameTypeKind (type: MappedType): MappedTypeNameTypeKind {
13927
13933
const nameType = getNameTypeFromMappedType(type);
13928
- return !!nameType && isTypeAssignableTo(nameType, getTypeParameterFromMappedType(type));
13934
+ if (!nameType) {
13935
+ return MappedTypeNameTypeKind.None;
13936
+ }
13937
+ return isTypeAssignableTo(nameType, getTypeParameterFromMappedType(type)) ? MappedTypeNameTypeKind.Filtering : MappedTypeNameTypeKind.Remapping;
13929
13938
}
13930
13939
13931
13940
function resolveStructuredTypeMembers(type: StructuredType): ResolvedType {
@@ -17700,7 +17709,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
17700
17709
function shouldDeferIndexType(type: Type, indexFlags = IndexFlags.None) {
17701
17710
return !!(type.flags & TypeFlags.InstantiableNonPrimitive ||
17702
17711
isGenericTupleType(type) ||
17703
- isGenericMappedType(type) && !hasDistributiveNameType(type) ||
17712
+ isGenericMappedType(type) && ( !hasDistributiveNameType(type) || getMappedTypeNameTypeKind(type) === MappedTypeNameTypeKind.Remapping ) ||
17704
17713
type.flags & TypeFlags.Union && !(indexFlags & IndexFlags.NoReducibleCheck) && isGenericReducibleType(type) ||
17705
17714
type.flags & TypeFlags.Intersection && maybeTypeOfKind(type, TypeFlags.Instantiable) && some((type as IntersectionType).types, isEmptyAnonymousObjectType));
17706
17715
}
@@ -18282,7 +18291,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
18282
18291
// K is generic and N is assignable to P, instantiate E using a mapper that substitutes the index type for P.
18283
18292
// For example, for an index access { [P in K]: Box<T[P]> }[X], we construct the type Box<T[X]>.
18284
18293
if (isGenericMappedType(objectType)) {
18285
- if (!getNameTypeFromMappedType (objectType) || isFilteringMappedType(objectType) ) {
18294
+ if (getMappedTypeNameTypeKind (objectType) !== MappedTypeNameTypeKind.Remapping ) {
18286
18295
return type[cache] = mapType(substituteIndexedMappedType(objectType, type.indexType), t => getSimplifiedType(t, writing));
18287
18296
}
18288
18297
}
@@ -40108,7 +40117,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
40108
40117
// Check if the index type is assignable to 'keyof T' for the object type.
40109
40118
const objectType = (type as IndexedAccessType).objectType;
40110
40119
const indexType = (type as IndexedAccessType).indexType;
40111
- if (isTypeAssignableTo(indexType, getIndexType(objectType, IndexFlags.None))) {
40120
+ // skip index type deferral on remapping mapped types
40121
+ const objectIndexType = isGenericMappedType(objectType) && getMappedTypeNameTypeKind(objectType) === MappedTypeNameTypeKind.Remapping
40122
+ ? getIndexTypeForMappedType(objectType, IndexFlags.None)
40123
+ : getIndexType(objectType, IndexFlags.None);
40124
+ if (isTypeAssignableTo(indexType, objectIndexType)) {
40112
40125
if (
40113
40126
accessNode.kind === SyntaxKind.ElementAccessExpression && isAssignmentTarget(accessNode) &&
40114
40127
getObjectFlags(objectType) & ObjectFlags.Mapped && getMappedTypeModifiers(objectType as MappedType) & MappedTypeModifiers.IncludeReadonly
0 commit comments