diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 76e81a959790b..5d37db197b879 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -26727,7 +26727,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } if (!inference.isFixed) { const candidate = propagationType || source; - if (candidate === blockedStringType) { + // ReturnMapper inferences are used only for contextual types. We exclude `any` and `unknown` types + // that might otherwise swallow other useful inferences. + if (candidate === blockedStringType || candidate.flags & TypeFlags.AnyOrUnknown && priority & InferencePriority.ReturnMapper) { return; } if (inference.priority === undefined || priority < inference.priority) { @@ -35698,7 +35700,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // type parameters for which the inferences are being made. const returnContext = createInferenceContext(signature.typeParameters!, signature, context.flags); const returnSourceType = instantiateType(contextualType, outerContext && createOuterReturnMapper(outerContext)); - inferTypes(returnContext.inferences, returnSourceType, inferenceTargetType); + inferTypes(returnContext.inferences, returnSourceType, inferenceTargetType, InferencePriority.ReturnMapper); context.returnMapper = some(returnContext.inferences, hasInferenceCandidates) ? getMapperFromContext(cloneInferredPartOfContext(returnContext)) : undefined; } } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index ee7f4338a3a10..fd03eb7be5d8f 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -7103,9 +7103,10 @@ export const enum InferencePriority { LiteralKeyof = 1 << 8, // Inference made from a string literal to a keyof T NoConstraints = 1 << 9, // Don't infer from constraints of instantiable types AlwaysStrict = 1 << 10, // Always use strict rules for contravariant inferences - MaxValue = 1 << 11, // Seed for inference priority tracking + ReturnMapper = 1 << 11, // Inferring for return mapper + MaxValue = 1 << 12, // Seed for inference priority tracking - PriorityImpliesCombination = ReturnType | MappedTypeConstraint | LiteralKeyof, // These priorities imply that the resulting type should be a combination of all candidates + PriorityImpliesCombination = ReturnType | ReturnMapper | MappedTypeConstraint | LiteralKeyof, // These priorities imply that the resulting type should be a combination of all candidates Circularity = -1, // Inference circularity (value less than all other priorities) } @@ -7129,6 +7130,7 @@ export const enum InferenceFlags { NoDefault = 1 << 0, // Infer silentNeverType for no inferences (otherwise anyType or unknownType) AnyDefault = 1 << 1, // Infer anyType (in JS files) for no inferences (otherwise unknownType) SkippedGenericFunction = 1 << 2, // A generic function was skipped during inference + NoUnknownInference = 1 << 3, } /** diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 2c56042e22d0c..06069be6d6e28 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -6894,8 +6894,9 @@ declare namespace ts { LiteralKeyof = 256, NoConstraints = 512, AlwaysStrict = 1024, - MaxValue = 2048, - PriorityImpliesCombination = 416, + ReturnMapper = 2048, + MaxValue = 4096, + PriorityImpliesCombination = 2464, Circularity = -1, } interface FileExtensionInfo {