diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index ff5d1c661e..4f2f065f4f 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -10386,7 +10386,7 @@ namespace ts { // results for union and intersection types for performance reasons. function couldContainTypeVariables(type: Type): boolean { const objectFlags = getObjectFlags(type); - return !!(type.flags & TypeFlags.TypeVariable || + return !!(type.flags & (TypeFlags.TypeVariable | TypeFlags.Index) || objectFlags & ObjectFlags.Reference && forEach((type).typeArguments, couldContainTypeVariables) || objectFlags & ObjectFlags.Anonymous && type.symbol && type.symbol.flags & (SymbolFlags.Function | SymbolFlags.Method | SymbolFlags.TypeLiteral | SymbolFlags.Class) || objectFlags & ObjectFlags.Mapped || @@ -10554,6 +10554,13 @@ namespace ts { inferFromTypes(sourceTypes[i], targetTypes[i]); } } + else if (source.flags & TypeFlags.Index && target.flags & TypeFlags.Index) { + inferFromTypes((source).type, (target).type); + } + else if (source.flags & TypeFlags.IndexedAccess && target.flags & TypeFlags.IndexedAccess) { + inferFromTypes((source).objectType, (target).objectType); + inferFromTypes((source).indexType, (target).indexType); + } else if (target.flags & TypeFlags.UnionOrIntersection) { const targetTypes = (target).types; let typeVariableCount = 0; @@ -10627,6 +10634,12 @@ namespace ts { } function inferFromObjectTypes(source: Type, target: Type) { + if (isGenericMappedType(source) && isGenericMappedType(target)) { + // The source and target types are generic types { [P in S]: X } and { [P in T]: Y }, so we infer + // from S to T and from X to Y. + inferFromTypes(getConstraintTypeFromMappedType(source), getConstraintTypeFromMappedType(target)); + inferFromTypes(getTemplateTypeFromMappedType(source), getTemplateTypeFromMappedType(target)); + } if (getObjectFlags(target) & ObjectFlags.Mapped) { const constraintType = getConstraintTypeFromMappedType(target); if (constraintType.flags & TypeFlags.Index) {