@@ -1304,6 +1304,12 @@ const enum MappedTypeModifiers {
13041304 ExcludeOptional = 1 << 3,
13051305}
13061306
1307+ const enum MappedTypeNameTypeKind {
1308+ None,
1309+ Filtering,
1310+ Remapping,
1311+ }
1312+
13071313const enum ExpandingFlags {
13081314 None = 0,
13091315 Source = 1,
@@ -13741,7 +13747,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1374113747 const constraintType = getConstraintTypeFromMappedType(type);
1374213748 const mappedType = (type.target as MappedType) || type;
1374313749 const nameType = getNameTypeFromMappedType(mappedType);
13744- const shouldLinkPropDeclarations = !nameType || isFilteringMappedType (mappedType);
13750+ const shouldLinkPropDeclarations = getMappedTypeNameTypeKind (mappedType) !== MappedTypeNameTypeKind.Remapping ;
1374513751 const templateType = getTemplateTypeFromMappedType(mappedType);
1374613752 const modifiersType = getApparentType(getModifiersTypeFromMappedType(type)); // The 'T' in 'keyof T'
1374713753 const templateModifiers = getMappedTypeModifiers(type);
@@ -13923,9 +13929,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1392313929 return false;
1392413930 }
1392513931
13926- function isFilteringMappedType (type: MappedType): boolean {
13932+ function getMappedTypeNameTypeKind (type: MappedType): MappedTypeNameTypeKind {
1392713933 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;
1392913938 }
1393013939
1393113940 function resolveStructuredTypeMembers(type: StructuredType): ResolvedType {
@@ -17700,7 +17709,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1770017709 function shouldDeferIndexType(type: Type, indexFlags = IndexFlags.None) {
1770117710 return !!(type.flags & TypeFlags.InstantiableNonPrimitive ||
1770217711 isGenericTupleType(type) ||
17703- isGenericMappedType(type) && !hasDistributiveNameType(type) ||
17712+ isGenericMappedType(type) && ( !hasDistributiveNameType(type) || getMappedTypeNameTypeKind(type) === MappedTypeNameTypeKind.Remapping ) ||
1770417713 type.flags & TypeFlags.Union && !(indexFlags & IndexFlags.NoReducibleCheck) && isGenericReducibleType(type) ||
1770517714 type.flags & TypeFlags.Intersection && maybeTypeOfKind(type, TypeFlags.Instantiable) && some((type as IntersectionType).types, isEmptyAnonymousObjectType));
1770617715 }
@@ -18282,7 +18291,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1828218291 // K is generic and N is assignable to P, instantiate E using a mapper that substitutes the index type for P.
1828318292 // For example, for an index access { [P in K]: Box<T[P]> }[X], we construct the type Box<T[X]>.
1828418293 if (isGenericMappedType(objectType)) {
18285- if (!getNameTypeFromMappedType (objectType) || isFilteringMappedType(objectType) ) {
18294+ if (getMappedTypeNameTypeKind (objectType) !== MappedTypeNameTypeKind.Remapping ) {
1828618295 return type[cache] = mapType(substituteIndexedMappedType(objectType, type.indexType), t => getSimplifiedType(t, writing));
1828718296 }
1828818297 }
@@ -40108,7 +40117,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
4010840117 // Check if the index type is assignable to 'keyof T' for the object type.
4010940118 const objectType = (type as IndexedAccessType).objectType;
4011040119 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)) {
4011240125 if (
4011340126 accessNode.kind === SyntaxKind.ElementAccessExpression && isAssignmentTarget(accessNode) &&
4011440127 getObjectFlags(objectType) & ObjectFlags.Mapped && getMappedTypeModifiers(objectType as MappedType) & MappedTypeModifiers.IncludeReadonly
0 commit comments