From 1bb1d2a6105a9a05a10409265f35cbe37d89b3e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Fri, 9 Aug 2024 05:24:10 +0200 Subject: [PATCH] Fixed regression in generic signature instantiation with default type args (#59510) --- src/compiler/checker.ts | 8 +- ...nericCallInferenceConditionalType2.symbols | 85 ++++++++++++++++ ...genericCallInferenceConditionalType2.types | 98 +++++++++++++++++++ .../genericCallInferenceConditionalType2.ts | 29 ++++++ 4 files changed, 218 insertions(+), 2 deletions(-) create mode 100644 tests/baselines/reference/genericCallInferenceConditionalType2.symbols create mode 100644 tests/baselines/reference/genericCallInferenceConditionalType2.types create mode 100644 tests/cases/compiler/genericCallInferenceConditionalType2.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 9ca49d3cdee..4b8d44e62fc 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -16040,8 +16040,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return instantiateSignature(signature, createSignatureTypeMapper(signature, typeArguments), /*eraseTypeParameters*/ true); } + function getTypeParametersForMapper(signature: Signature) { + return sameMap(signature.typeParameters, tp => tp.mapper ? instantiateType(tp, tp.mapper) : tp); + } + function createSignatureTypeMapper(signature: Signature, typeArguments: readonly Type[] | undefined): TypeMapper { - return createTypeMapper(sameMap(signature.typeParameters!, tp => tp.mapper ? instantiateType(tp, tp.mapper) : tp), typeArguments); + return createTypeMapper(getTypeParametersForMapper(signature)!, typeArguments); } function getErasedSignature(signature: Signature): Signature { @@ -34930,7 +34934,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // Instantiate a generic signature in the context of a non-generic signature (section 3.8.5 in TypeScript spec) function instantiateSignatureInContextOf(signature: Signature, contextualSignature: Signature, inferenceContext?: InferenceContext, compareTypes?: TypeComparer): Signature { - const context = createInferenceContext(signature.typeParameters!, signature, InferenceFlags.None, compareTypes); + const context = createInferenceContext(getTypeParametersForMapper(signature)!, signature, InferenceFlags.None, compareTypes); // We clone the inferenceContext to avoid fixing. For example, when the source signature is (x: T) => T[] and // the contextual signature is (...args: A) => B, we want to infer the element type of A's constraint (say 'any') // for T but leave it possible to later infer '[any]' back to A. diff --git a/tests/baselines/reference/genericCallInferenceConditionalType2.symbols b/tests/baselines/reference/genericCallInferenceConditionalType2.symbols new file mode 100644 index 00000000000..1f88ec594ad --- /dev/null +++ b/tests/baselines/reference/genericCallInferenceConditionalType2.symbols @@ -0,0 +1,85 @@ +//// [tests/cases/compiler/genericCallInferenceConditionalType2.ts] //// + +=== genericCallInferenceConditionalType2.ts === +// https://github.com/microsoft/TypeScript/issues/59490 + +type ComponentProps = T extends (props: infer P) => unknown ? P : never; +>ComponentProps : Symbol(ComponentProps, Decl(genericCallInferenceConditionalType2.ts, 0, 0)) +>T : Symbol(T, Decl(genericCallInferenceConditionalType2.ts, 2, 20)) +>T : Symbol(T, Decl(genericCallInferenceConditionalType2.ts, 2, 20)) +>props : Symbol(props, Decl(genericCallInferenceConditionalType2.ts, 2, 36)) +>P : Symbol(P, Decl(genericCallInferenceConditionalType2.ts, 2, 48)) +>P : Symbol(P, Decl(genericCallInferenceConditionalType2.ts, 2, 48)) + +declare function wrapComponent

( +>wrapComponent : Symbol(wrapComponent, Decl(genericCallInferenceConditionalType2.ts, 2, 75)) +>P : Symbol(P, Decl(genericCallInferenceConditionalType2.ts, 4, 31)) + + component: (props: P) => unknown, +>component : Symbol(component, Decl(genericCallInferenceConditionalType2.ts, 4, 34)) +>props : Symbol(props, Decl(genericCallInferenceConditionalType2.ts, 5, 14)) +>P : Symbol(P, Decl(genericCallInferenceConditionalType2.ts, 4, 31)) + +): (props: P) => unknown; +>props : Symbol(props, Decl(genericCallInferenceConditionalType2.ts, 6, 4)) +>P : Symbol(P, Decl(genericCallInferenceConditionalType2.ts, 4, 31)) + +const WrappedComponent = wrapComponent( +>WrappedComponent : Symbol(WrappedComponent, Decl(genericCallInferenceConditionalType2.ts, 8, 5)) +>wrapComponent : Symbol(wrapComponent, Decl(genericCallInferenceConditionalType2.ts, 2, 75)) + + (props: { +>T : Symbol(T, Decl(genericCallInferenceConditionalType2.ts, 9, 3)) +>props : Symbol(props, Decl(genericCallInferenceConditionalType2.ts, 9, 30)) + + as?: T | undefined; +>as : Symbol(as, Decl(genericCallInferenceConditionalType2.ts, 9, 38)) +>T : Symbol(T, Decl(genericCallInferenceConditionalType2.ts, 9, 3)) + + className?: string; +>className : Symbol(className, Decl(genericCallInferenceConditionalType2.ts, 10, 23)) + + }) => { + return null; + }, +); + +type RetrievedProps = ComponentProps; +>RetrievedProps : Symbol(RetrievedProps, Decl(genericCallInferenceConditionalType2.ts, 15, 2)) +>ComponentProps : Symbol(ComponentProps, Decl(genericCallInferenceConditionalType2.ts, 0, 0)) +>WrappedComponent : Symbol(WrappedComponent, Decl(genericCallInferenceConditionalType2.ts, 8, 5)) + +declare const f: (f: (x: T) => unknown) => (x: T) => unknown +>f : Symbol(f, Decl(genericCallInferenceConditionalType2.ts, 19, 13)) +>T : Symbol(T, Decl(genericCallInferenceConditionalType2.ts, 19, 18)) +>f : Symbol(f, Decl(genericCallInferenceConditionalType2.ts, 19, 21)) +>x : Symbol(x, Decl(genericCallInferenceConditionalType2.ts, 19, 25)) +>T : Symbol(T, Decl(genericCallInferenceConditionalType2.ts, 19, 18)) +>x : Symbol(x, Decl(genericCallInferenceConditionalType2.ts, 19, 47)) +>T : Symbol(T, Decl(genericCallInferenceConditionalType2.ts, 19, 18)) + +declare const g: (x: { foo: T }) => unknown +>g : Symbol(g, Decl(genericCallInferenceConditionalType2.ts, 20, 13)) +>T : Symbol(T, Decl(genericCallInferenceConditionalType2.ts, 20, 18)) +>x : Symbol(x, Decl(genericCallInferenceConditionalType2.ts, 20, 46)) +>foo : Symbol(foo, Decl(genericCallInferenceConditionalType2.ts, 20, 50)) +>T : Symbol(T, Decl(genericCallInferenceConditionalType2.ts, 20, 18)) + +const h = f(g) +>h : Symbol(h, Decl(genericCallInferenceConditionalType2.ts, 22, 5)) +>f : Symbol(f, Decl(genericCallInferenceConditionalType2.ts, 19, 13)) +>g : Symbol(g, Decl(genericCallInferenceConditionalType2.ts, 20, 13)) + +type FirstParameter = T extends (x: infer P) => unknown ? P : unknown +>FirstParameter : Symbol(FirstParameter, Decl(genericCallInferenceConditionalType2.ts, 22, 14)) +>T : Symbol(T, Decl(genericCallInferenceConditionalType2.ts, 24, 20)) +>T : Symbol(T, Decl(genericCallInferenceConditionalType2.ts, 24, 20)) +>x : Symbol(x, Decl(genericCallInferenceConditionalType2.ts, 24, 36)) +>P : Symbol(P, Decl(genericCallInferenceConditionalType2.ts, 24, 44)) +>P : Symbol(P, Decl(genericCallInferenceConditionalType2.ts, 24, 44)) + +type X = FirstParameter['foo'] +>X : Symbol(X, Decl(genericCallInferenceConditionalType2.ts, 24, 72)) +>FirstParameter : Symbol(FirstParameter, Decl(genericCallInferenceConditionalType2.ts, 22, 14)) +>h : Symbol(h, Decl(genericCallInferenceConditionalType2.ts, 22, 5)) + diff --git a/tests/baselines/reference/genericCallInferenceConditionalType2.types b/tests/baselines/reference/genericCallInferenceConditionalType2.types new file mode 100644 index 00000000000..c9c143a7dd8 --- /dev/null +++ b/tests/baselines/reference/genericCallInferenceConditionalType2.types @@ -0,0 +1,98 @@ +//// [tests/cases/compiler/genericCallInferenceConditionalType2.ts] //// + +=== genericCallInferenceConditionalType2.ts === +// https://github.com/microsoft/TypeScript/issues/59490 + +type ComponentProps = T extends (props: infer P) => unknown ? P : never; +>ComponentProps : ComponentProps +> : ^^^^^^^^^^^^^^^^^ +>props : P +> : ^ + +declare function wrapComponent

( +>wrapComponent :

(component: (props: P) => unknown) => (props: P) => unknown +> : ^ ^^ ^^ ^^^^^ + + component: (props: P) => unknown, +>component : (props: P) => unknown +> : ^ ^^ ^^^^^ +>props : P +> : ^ + +): (props: P) => unknown; +>props : P +> : ^ + +const WrappedComponent = wrapComponent( +>WrappedComponent : (props: { as?: T | undefined; className?: string; }) => unknown +> : ^ ^^^^^^^^^ ^^^^^^^^^^^ ^^^^^^^^^ ^^^^^^^^^^^^^^ ^^^^^^^^ +>wrapComponent( (props: { as?: T | undefined; className?: string; }) => { return null; },) : (props: { as?: T | undefined; className?: string; }) => unknown +> : ^ ^^^^^^^^^ ^^^^^^^^^^^ ^^^^^^^^^ ^^^^^^^^^^^^^^ ^^^^^^^^ +>wrapComponent :

(component: (props: P) => unknown) => (props: P) => unknown +> : ^ ^^ ^^ ^^^^^ + + (props: { +>(props: { as?: T | undefined; className?: string; }) => { return null; } : (props: { as?: T | undefined; className?: string; }) => null +> : ^ ^^^^^^^^^ ^^^^^^^^^^^ ^^ ^^^^^^^^^ +>props : { as?: T | undefined; className?: string; } +> : ^^^^^^^ ^^^^^^^^^^^^^^ ^^^ + + as?: T | undefined; +>as : T | undefined +> : ^^^^^^^^^^^^^ + + className?: string; +>className : string | undefined +> : ^^^^^^^^^^^^^^^^^^ + + }) => { + return null; + }, +); + +type RetrievedProps = ComponentProps; +>RetrievedProps : { as?: string | undefined; className?: string; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^ +>WrappedComponent : (props: { as?: T | undefined; className?: string; }) => unknown +> : ^ ^^^^^^^^^ ^^^^^^^^^^^ ^^^^^^^^^ ^^^^^^^^^^^^^^ ^^^^^^^^ + +declare const f: (f: (x: T) => unknown) => (x: T) => unknown +>f : (f: (x: T) => unknown) => (x: T) => unknown +> : ^ ^^ ^^ ^^^^^ +>f : (x: T) => unknown +> : ^ ^^ ^^^^^ +>x : T +> : ^ +>x : T +> : ^ + +declare const g: (x: { foo: T }) => unknown +>g : (x: { foo: T; }) => unknown +> : ^ ^^^^^^^^^ ^^^^^^^^^^^ ^^ ^^^^^ +>x : { foo: T; } +> : ^^^^^^^ ^^^ +>foo : T +> : ^ + +const h = f(g) +>h : (x: { foo: T; }) => unknown +> : ^ ^^^^^^^^^ ^^^^^^^^^^^ ^^^^^^^^^ ^^^^^^^^ +>f(g) : (x: { foo: T; }) => unknown +> : ^ ^^^^^^^^^ ^^^^^^^^^^^ ^^^^^^^^^ ^^^^^^^^ +>f : (f: (x: T) => unknown) => (x: T) => unknown +> : ^ ^^ ^^ ^^^^^ +>g : (x: { foo: T; }) => unknown +> : ^ ^^^^^^^^^ ^^^^^^^^^^^ ^^ ^^^^^ + +type FirstParameter = T extends (x: infer P) => unknown ? P : unknown +>FirstParameter : FirstParameter +> : ^^^^^^^^^^^^^^^^^ +>x : P +> : ^ + +type X = FirstParameter['foo'] +>X : unknown +> : ^^^^^^^ +>h : (x: { foo: T; }) => unknown +> : ^ ^^^^^^^^^ ^^^^^^^^^^^ ^^^^^^^^^ ^^^^^^^^ + diff --git a/tests/cases/compiler/genericCallInferenceConditionalType2.ts b/tests/cases/compiler/genericCallInferenceConditionalType2.ts new file mode 100644 index 00000000000..38afcf985ef --- /dev/null +++ b/tests/cases/compiler/genericCallInferenceConditionalType2.ts @@ -0,0 +1,29 @@ +// @strict: true +// @noEmit: true + +// https://github.com/microsoft/TypeScript/issues/59490 + +type ComponentProps = T extends (props: infer P) => unknown ? P : never; + +declare function wrapComponent

( + component: (props: P) => unknown, +): (props: P) => unknown; + +const WrappedComponent = wrapComponent( + (props: { + as?: T | undefined; + className?: string; + }) => { + return null; + }, +); + +type RetrievedProps = ComponentProps; + +declare const f: (f: (x: T) => unknown) => (x: T) => unknown +declare const g: (x: { foo: T }) => unknown + +const h = f(g) + +type FirstParameter = T extends (x: infer P) => unknown ? P : unknown +type X = FirstParameter['foo']