From 80f7af3a0f1b1e186585e9d3ab6fc671873d3611 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Thu, 9 Jan 2025 00:04:23 +0100 Subject: [PATCH] Infer from constraints of type parameters in generic signatures --- src/compiler/checker.ts | 14 ++++++-- ...ericSignatureTypeParamConstraints1.symbols | 32 +++++++++++++++++++ ...enericSignatureTypeParamConstraints1.types | 26 +++++++++++++++ ...omGenericSignatureTypeParamConstraints1.ts | 13 ++++++++ 4 files changed, 83 insertions(+), 2 deletions(-) create mode 100644 tests/baselines/reference/inferenceFromGenericSignatureTypeParamConstraints1.symbols create mode 100644 tests/baselines/reference/inferenceFromGenericSignatureTypeParamConstraints1.types create mode 100644 tests/cases/compiler/inferenceFromGenericSignatureTypeParamConstraints1.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 80b61edd3657a..33fb339695ef5 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -26842,8 +26842,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const targetSignatures = getSignaturesOfType(target, kind); const targetLen = targetSignatures.length; for (let i = 0; i < targetLen; i++) { - const sourceIndex = Math.max(sourceLen - targetLen + i, 0); - inferFromSignature(getBaseSignature(sourceSignatures[sourceIndex]), getErasedSignature(targetSignatures[i])); + const sourceSignature = sourceSignatures[Math.max(sourceLen - targetLen + i, 0)]; + const targetSignature = targetSignatures[i]; + if (targetSignature.typeParameters && targetSignature.typeParameters.length === sourceSignature.typeParameters?.length) { + for (let j = 0; j < targetSignature.typeParameters.length; j++) { + const sourceTypeParameter = sourceSignature.typeParameters[j]; + const targetTypeParameter = targetSignature.typeParameters[j]; + if (sourceTypeParameter.constraint && targetTypeParameter.constraint) { + inferFromTypes(sourceTypeParameter.constraint, targetTypeParameter.constraint); + } + } + } + inferFromSignature(getBaseSignature(sourceSignature), getErasedSignature(targetSignature)); } } } diff --git a/tests/baselines/reference/inferenceFromGenericSignatureTypeParamConstraints1.symbols b/tests/baselines/reference/inferenceFromGenericSignatureTypeParamConstraints1.symbols new file mode 100644 index 0000000000000..8c36fa2e854d8 --- /dev/null +++ b/tests/baselines/reference/inferenceFromGenericSignatureTypeParamConstraints1.symbols @@ -0,0 +1,32 @@ +//// [tests/cases/compiler/inferenceFromGenericSignatureTypeParamConstraints1.ts] //// + +=== inferenceFromGenericSignatureTypeParamConstraints1.ts === +// https://github.com/microsoft/TypeScript/issues/41040 + +type InferGenericConstraint = +>InferGenericConstraint : Symbol(InferGenericConstraint, Decl(inferenceFromGenericSignatureTypeParamConstraints1.ts, 0, 0)) +>Fn : Symbol(Fn, Decl(inferenceFromGenericSignatureTypeParamConstraints1.ts, 2, 28)) + + Fn extends (arg: T) => any +>Fn : Symbol(Fn, Decl(inferenceFromGenericSignatureTypeParamConstraints1.ts, 2, 28)) +>T : Symbol(T, Decl(inferenceFromGenericSignatureTypeParamConstraints1.ts, 3, 16)) +>Constraint : Symbol(Constraint, Decl(inferenceFromGenericSignatureTypeParamConstraints1.ts, 3, 31)) +>arg : Symbol(arg, Decl(inferenceFromGenericSignatureTypeParamConstraints1.ts, 3, 44)) +>T : Symbol(T, Decl(inferenceFromGenericSignatureTypeParamConstraints1.ts, 3, 16)) + + ? Constraint +>Constraint : Symbol(Constraint, Decl(inferenceFromGenericSignatureTypeParamConstraints1.ts, 3, 31)) + + : never; + +type GenericFunctionExample = (arg: T) => void; +>GenericFunctionExample : Symbol(GenericFunctionExample, Decl(inferenceFromGenericSignatureTypeParamConstraints1.ts, 5, 16)) +>T : Symbol(T, Decl(inferenceFromGenericSignatureTypeParamConstraints1.ts, 7, 31)) +>arg : Symbol(arg, Decl(inferenceFromGenericSignatureTypeParamConstraints1.ts, 7, 49)) +>T : Symbol(T, Decl(inferenceFromGenericSignatureTypeParamConstraints1.ts, 7, 31)) + +type InferredConstraint = InferGenericConstraint; +>InferredConstraint : Symbol(InferredConstraint, Decl(inferenceFromGenericSignatureTypeParamConstraints1.ts, 7, 65)) +>InferGenericConstraint : Symbol(InferGenericConstraint, Decl(inferenceFromGenericSignatureTypeParamConstraints1.ts, 0, 0)) +>GenericFunctionExample : Symbol(GenericFunctionExample, Decl(inferenceFromGenericSignatureTypeParamConstraints1.ts, 5, 16)) + diff --git a/tests/baselines/reference/inferenceFromGenericSignatureTypeParamConstraints1.types b/tests/baselines/reference/inferenceFromGenericSignatureTypeParamConstraints1.types new file mode 100644 index 0000000000000..d5da17312bfbf --- /dev/null +++ b/tests/baselines/reference/inferenceFromGenericSignatureTypeParamConstraints1.types @@ -0,0 +1,26 @@ +//// [tests/cases/compiler/inferenceFromGenericSignatureTypeParamConstraints1.ts] //// + +=== inferenceFromGenericSignatureTypeParamConstraints1.ts === +// https://github.com/microsoft/TypeScript/issues/41040 + +type InferGenericConstraint = +>InferGenericConstraint : InferGenericConstraint +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^ + + Fn extends (arg: T) => any +>arg : T +> : ^ + + ? Constraint + : never; + +type GenericFunctionExample = (arg: T) => void; +>GenericFunctionExample : GenericFunctionExample +> : ^^^^^^^^^^^^^^^^^^^^^^ +>arg : T +> : ^ + +type InferredConstraint = InferGenericConstraint; +>InferredConstraint : number +> : ^^^^^^ + diff --git a/tests/cases/compiler/inferenceFromGenericSignatureTypeParamConstraints1.ts b/tests/cases/compiler/inferenceFromGenericSignatureTypeParamConstraints1.ts new file mode 100644 index 0000000000000..4408718eee475 --- /dev/null +++ b/tests/cases/compiler/inferenceFromGenericSignatureTypeParamConstraints1.ts @@ -0,0 +1,13 @@ +// @noEmit: true +// @strict: true + +// https://github.com/microsoft/TypeScript/issues/41040 + +type InferGenericConstraint = + Fn extends (arg: T) => any + ? Constraint + : never; + +type GenericFunctionExample = (arg: T) => void; + +type InferredConstraint = InferGenericConstraint;