diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index ecbc98ee4955c..cf5c410995de8 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -22556,15 +22556,11 @@ namespace ts { inferFromTypeArguments(getTypeArguments(source as TypeReference), getTypeArguments(target as TypeReference), getVariances((source as TypeReference).target)); } else if (source.flags & TypeFlags.Index && target.flags & TypeFlags.Index) { - contravariant = !contravariant; - inferFromTypes((source as IndexType).type, (target as IndexType).type); - contravariant = !contravariant; + inferFromContravariantTypes((source as IndexType).type, (target as IndexType).type); } else if ((isLiteralType(source) || source.flags & TypeFlags.String) && target.flags & TypeFlags.Index) { const empty = createEmptyObjectTypeFromStringLiteral(source); - contravariant = !contravariant; - inferWithPriority(empty, (target as IndexType).type, InferencePriority.LiteralKeyof); - contravariant = !contravariant; + inferFromContravariantTypesWithPriority(empty, (target as IndexType).type, InferencePriority.LiteralKeyof); } else if (source.flags & TypeFlags.IndexedAccess && target.flags & TypeFlags.IndexedAccess) { inferFromTypes((source as IndexedAccessType).objectType, (target as IndexedAccessType).objectType); @@ -22577,10 +22573,7 @@ namespace ts { } else if (source.flags & TypeFlags.Substitution) { inferFromTypes((source as SubstitutionType).baseType, target); - const oldPriority = priority; - priority |= InferencePriority.SubstituteSource; - inferFromTypes((source as SubstitutionType).substitute, target); // Make substitute inference at a lower priority - priority = oldPriority; + inferWithPriority((source as SubstitutionType).substitute, target, InferencePriority.SubstituteSource); // Make substitute inference at a lower priority } else if (target.flags & TypeFlags.Conditional) { invokeOnce(source, target, inferToConditionalType); @@ -22631,6 +22624,20 @@ namespace ts { priority = savePriority; } + function inferFromContravariantTypesWithPriority(source: Type, target: Type, newPriority: InferencePriority) { + const savePriority = priority; + priority |= newPriority; + inferFromContravariantTypes(source, target); + priority = savePriority; + } + + function inferToMultipleTypesWithPriority(source: Type, targets: Type[], targetFlags: TypeFlags, newPriority: InferencePriority) { + const savePriority = priority; + priority |= newPriority; + inferToMultipleTypes(source, targets, targetFlags); + priority = savePriority; + } + function invokeOnce(source: Type, target: Type, action: (source: Type, target: Type) => void) { const key = source.id + "," + target.id; const status = visited && visited.get(key); @@ -22694,10 +22701,14 @@ namespace ts { } function inferFromContravariantTypes(source: Type, target: Type) { + contravariant = !contravariant; + inferFromTypes(source, target); + contravariant = !contravariant; + } + + function inferFromContravariantTypesIfStrictFunctionTypes(source: Type, target: Type) { if (strictFunctionTypes || priority & InferencePriority.AlwaysStrict) { - contravariant = !contravariant; - inferFromTypes(source, target); - contravariant = !contravariant; + inferFromContravariantTypes(source, target); } else { inferFromTypes(source, target); @@ -22860,11 +22871,8 @@ namespace ts { inferFromTypes(getFalseTypeFromConditionalType(source as ConditionalType), getFalseTypeFromConditionalType(target)); } else { - const savePriority = priority; - priority |= contravariant ? InferencePriority.ContravariantConditional : 0; const targetTypes = [getTrueTypeFromConditionalType(target), getFalseTypeFromConditionalType(target)]; - inferToMultipleTypes(source, targetTypes, target.flags); - priority = savePriority; + inferToMultipleTypesWithPriority(source, targetTypes, target.flags, contravariant ? InferencePriority.ContravariantConditional : 0); } } @@ -23059,7 +23067,7 @@ namespace ts { const kind = target.declaration ? target.declaration.kind : SyntaxKind.Unknown; // Once we descend into a bivariant signature we remain bivariant for all nested inferences bivariant = bivariant || kind === SyntaxKind.MethodDeclaration || kind === SyntaxKind.MethodSignature || kind === SyntaxKind.Constructor; - applyToParameterTypes(source, target, inferFromContravariantTypes); + applyToParameterTypes(source, target, inferFromContravariantTypesIfStrictFunctionTypes); bivariant = saveBivariant; applyToReturnTypes(source, target, inferFromTypes); }