Skip to content

Commit 1bb1d2a

Browse files
authored
Fixed regression in generic signature instantiation with default type args (#59510)
1 parent 278cb94 commit 1bb1d2a

File tree

4 files changed

+218
-2
lines changed

4 files changed

+218
-2
lines changed

src/compiler/checker.ts

+6-2
Original file line numberDiff line numberDiff line change
@@ -16040,8 +16040,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1604016040
return instantiateSignature(signature, createSignatureTypeMapper(signature, typeArguments), /*eraseTypeParameters*/ true);
1604116041
}
1604216042

16043+
function getTypeParametersForMapper(signature: Signature) {
16044+
return sameMap(signature.typeParameters, tp => tp.mapper ? instantiateType(tp, tp.mapper) : tp);
16045+
}
16046+
1604316047
function createSignatureTypeMapper(signature: Signature, typeArguments: readonly Type[] | undefined): TypeMapper {
16044-
return createTypeMapper(sameMap(signature.typeParameters!, tp => tp.mapper ? instantiateType(tp, tp.mapper) : tp), typeArguments);
16048+
return createTypeMapper(getTypeParametersForMapper(signature)!, typeArguments);
1604516049
}
1604616050

1604716051
function getErasedSignature(signature: Signature): Signature {
@@ -34930,7 +34934,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
3493034934

3493134935
// Instantiate a generic signature in the context of a non-generic signature (section 3.8.5 in TypeScript spec)
3493234936
function instantiateSignatureInContextOf(signature: Signature, contextualSignature: Signature, inferenceContext?: InferenceContext, compareTypes?: TypeComparer): Signature {
34933-
const context = createInferenceContext(signature.typeParameters!, signature, InferenceFlags.None, compareTypes);
34937+
const context = createInferenceContext(getTypeParametersForMapper(signature)!, signature, InferenceFlags.None, compareTypes);
3493434938
// We clone the inferenceContext to avoid fixing. For example, when the source signature is <T>(x: T) => T[] and
3493534939
// the contextual signature is (...args: A) => B, we want to infer the element type of A's constraint (say 'any')
3493634940
// for T but leave it possible to later infer '[any]' back to A.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
//// [tests/cases/compiler/genericCallInferenceConditionalType2.ts] ////
2+
3+
=== genericCallInferenceConditionalType2.ts ===
4+
// https://github.com/microsoft/TypeScript/issues/59490
5+
6+
type ComponentProps<T> = T extends (props: infer P) => unknown ? P : never;
7+
>ComponentProps : Symbol(ComponentProps, Decl(genericCallInferenceConditionalType2.ts, 0, 0))
8+
>T : Symbol(T, Decl(genericCallInferenceConditionalType2.ts, 2, 20))
9+
>T : Symbol(T, Decl(genericCallInferenceConditionalType2.ts, 2, 20))
10+
>props : Symbol(props, Decl(genericCallInferenceConditionalType2.ts, 2, 36))
11+
>P : Symbol(P, Decl(genericCallInferenceConditionalType2.ts, 2, 48))
12+
>P : Symbol(P, Decl(genericCallInferenceConditionalType2.ts, 2, 48))
13+
14+
declare function wrapComponent<P>(
15+
>wrapComponent : Symbol(wrapComponent, Decl(genericCallInferenceConditionalType2.ts, 2, 75))
16+
>P : Symbol(P, Decl(genericCallInferenceConditionalType2.ts, 4, 31))
17+
18+
component: (props: P) => unknown,
19+
>component : Symbol(component, Decl(genericCallInferenceConditionalType2.ts, 4, 34))
20+
>props : Symbol(props, Decl(genericCallInferenceConditionalType2.ts, 5, 14))
21+
>P : Symbol(P, Decl(genericCallInferenceConditionalType2.ts, 4, 31))
22+
23+
): (props: P) => unknown;
24+
>props : Symbol(props, Decl(genericCallInferenceConditionalType2.ts, 6, 4))
25+
>P : Symbol(P, Decl(genericCallInferenceConditionalType2.ts, 4, 31))
26+
27+
const WrappedComponent = wrapComponent(
28+
>WrappedComponent : Symbol(WrappedComponent, Decl(genericCallInferenceConditionalType2.ts, 8, 5))
29+
>wrapComponent : Symbol(wrapComponent, Decl(genericCallInferenceConditionalType2.ts, 2, 75))
30+
31+
<T extends string = "span">(props: {
32+
>T : Symbol(T, Decl(genericCallInferenceConditionalType2.ts, 9, 3))
33+
>props : Symbol(props, Decl(genericCallInferenceConditionalType2.ts, 9, 30))
34+
35+
as?: T | undefined;
36+
>as : Symbol(as, Decl(genericCallInferenceConditionalType2.ts, 9, 38))
37+
>T : Symbol(T, Decl(genericCallInferenceConditionalType2.ts, 9, 3))
38+
39+
className?: string;
40+
>className : Symbol(className, Decl(genericCallInferenceConditionalType2.ts, 10, 23))
41+
42+
}) => {
43+
return null;
44+
},
45+
);
46+
47+
type RetrievedProps = ComponentProps<typeof WrappedComponent>;
48+
>RetrievedProps : Symbol(RetrievedProps, Decl(genericCallInferenceConditionalType2.ts, 15, 2))
49+
>ComponentProps : Symbol(ComponentProps, Decl(genericCallInferenceConditionalType2.ts, 0, 0))
50+
>WrappedComponent : Symbol(WrappedComponent, Decl(genericCallInferenceConditionalType2.ts, 8, 5))
51+
52+
declare const f: <T>(f: (x: T) => unknown) => (x: T) => unknown
53+
>f : Symbol(f, Decl(genericCallInferenceConditionalType2.ts, 19, 13))
54+
>T : Symbol(T, Decl(genericCallInferenceConditionalType2.ts, 19, 18))
55+
>f : Symbol(f, Decl(genericCallInferenceConditionalType2.ts, 19, 21))
56+
>x : Symbol(x, Decl(genericCallInferenceConditionalType2.ts, 19, 25))
57+
>T : Symbol(T, Decl(genericCallInferenceConditionalType2.ts, 19, 18))
58+
>x : Symbol(x, Decl(genericCallInferenceConditionalType2.ts, 19, 47))
59+
>T : Symbol(T, Decl(genericCallInferenceConditionalType2.ts, 19, 18))
60+
61+
declare const g: <T extends unknown = string>(x: { foo: T }) => unknown
62+
>g : Symbol(g, Decl(genericCallInferenceConditionalType2.ts, 20, 13))
63+
>T : Symbol(T, Decl(genericCallInferenceConditionalType2.ts, 20, 18))
64+
>x : Symbol(x, Decl(genericCallInferenceConditionalType2.ts, 20, 46))
65+
>foo : Symbol(foo, Decl(genericCallInferenceConditionalType2.ts, 20, 50))
66+
>T : Symbol(T, Decl(genericCallInferenceConditionalType2.ts, 20, 18))
67+
68+
const h = f(g)
69+
>h : Symbol(h, Decl(genericCallInferenceConditionalType2.ts, 22, 5))
70+
>f : Symbol(f, Decl(genericCallInferenceConditionalType2.ts, 19, 13))
71+
>g : Symbol(g, Decl(genericCallInferenceConditionalType2.ts, 20, 13))
72+
73+
type FirstParameter<T> = T extends (x: infer P) => unknown ? P : unknown
74+
>FirstParameter : Symbol(FirstParameter, Decl(genericCallInferenceConditionalType2.ts, 22, 14))
75+
>T : Symbol(T, Decl(genericCallInferenceConditionalType2.ts, 24, 20))
76+
>T : Symbol(T, Decl(genericCallInferenceConditionalType2.ts, 24, 20))
77+
>x : Symbol(x, Decl(genericCallInferenceConditionalType2.ts, 24, 36))
78+
>P : Symbol(P, Decl(genericCallInferenceConditionalType2.ts, 24, 44))
79+
>P : Symbol(P, Decl(genericCallInferenceConditionalType2.ts, 24, 44))
80+
81+
type X = FirstParameter<typeof h>['foo']
82+
>X : Symbol(X, Decl(genericCallInferenceConditionalType2.ts, 24, 72))
83+
>FirstParameter : Symbol(FirstParameter, Decl(genericCallInferenceConditionalType2.ts, 22, 14))
84+
>h : Symbol(h, Decl(genericCallInferenceConditionalType2.ts, 22, 5))
85+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
//// [tests/cases/compiler/genericCallInferenceConditionalType2.ts] ////
2+
3+
=== genericCallInferenceConditionalType2.ts ===
4+
// https://github.com/microsoft/TypeScript/issues/59490
5+
6+
type ComponentProps<T> = T extends (props: infer P) => unknown ? P : never;
7+
>ComponentProps : ComponentProps<T>
8+
> : ^^^^^^^^^^^^^^^^^
9+
>props : P
10+
> : ^
11+
12+
declare function wrapComponent<P>(
13+
>wrapComponent : <P>(component: (props: P) => unknown) => (props: P) => unknown
14+
> : ^ ^^ ^^ ^^^^^
15+
16+
component: (props: P) => unknown,
17+
>component : (props: P) => unknown
18+
> : ^ ^^ ^^^^^
19+
>props : P
20+
> : ^
21+
22+
): (props: P) => unknown;
23+
>props : P
24+
> : ^
25+
26+
const WrappedComponent = wrapComponent(
27+
>WrappedComponent : <T extends string = "span">(props: { as?: T | undefined; className?: string; }) => unknown
28+
> : ^ ^^^^^^^^^ ^^^^^^^^^^^ ^^^^^^^^^ ^^^^^^^^^^^^^^ ^^^^^^^^
29+
>wrapComponent( <T extends string = "span">(props: { as?: T | undefined; className?: string; }) => { return null; },) : <T extends string = "span">(props: { as?: T | undefined; className?: string; }) => unknown
30+
> : ^ ^^^^^^^^^ ^^^^^^^^^^^ ^^^^^^^^^ ^^^^^^^^^^^^^^ ^^^^^^^^
31+
>wrapComponent : <P>(component: (props: P) => unknown) => (props: P) => unknown
32+
> : ^ ^^ ^^ ^^^^^
33+
34+
<T extends string = "span">(props: {
35+
><T extends string = "span">(props: { as?: T | undefined; className?: string; }) => { return null; } : <T extends string = "span">(props: { as?: T | undefined; className?: string; }) => null
36+
> : ^ ^^^^^^^^^ ^^^^^^^^^^^ ^^ ^^^^^^^^^
37+
>props : { as?: T | undefined; className?: string; }
38+
> : ^^^^^^^ ^^^^^^^^^^^^^^ ^^^
39+
40+
as?: T | undefined;
41+
>as : T | undefined
42+
> : ^^^^^^^^^^^^^
43+
44+
className?: string;
45+
>className : string | undefined
46+
> : ^^^^^^^^^^^^^^^^^^
47+
48+
}) => {
49+
return null;
50+
},
51+
);
52+
53+
type RetrievedProps = ComponentProps<typeof WrappedComponent>;
54+
>RetrievedProps : { as?: string | undefined; className?: string; }
55+
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^
56+
>WrappedComponent : <T extends string = "span">(props: { as?: T | undefined; className?: string; }) => unknown
57+
> : ^ ^^^^^^^^^ ^^^^^^^^^^^ ^^^^^^^^^ ^^^^^^^^^^^^^^ ^^^^^^^^
58+
59+
declare const f: <T>(f: (x: T) => unknown) => (x: T) => unknown
60+
>f : <T>(f: (x: T) => unknown) => (x: T) => unknown
61+
> : ^ ^^ ^^ ^^^^^
62+
>f : (x: T) => unknown
63+
> : ^ ^^ ^^^^^
64+
>x : T
65+
> : ^
66+
>x : T
67+
> : ^
68+
69+
declare const g: <T extends unknown = string>(x: { foo: T }) => unknown
70+
>g : <T extends unknown = string>(x: { foo: T; }) => unknown
71+
> : ^ ^^^^^^^^^ ^^^^^^^^^^^ ^^ ^^^^^
72+
>x : { foo: T; }
73+
> : ^^^^^^^ ^^^
74+
>foo : T
75+
> : ^
76+
77+
const h = f(g)
78+
>h : <T extends unknown = string>(x: { foo: T; }) => unknown
79+
> : ^ ^^^^^^^^^ ^^^^^^^^^^^ ^^^^^^^^^ ^^^^^^^^
80+
>f(g) : <T extends unknown = string>(x: { foo: T; }) => unknown
81+
> : ^ ^^^^^^^^^ ^^^^^^^^^^^ ^^^^^^^^^ ^^^^^^^^
82+
>f : <T>(f: (x: T) => unknown) => (x: T) => unknown
83+
> : ^ ^^ ^^ ^^^^^
84+
>g : <T extends unknown = string>(x: { foo: T; }) => unknown
85+
> : ^ ^^^^^^^^^ ^^^^^^^^^^^ ^^ ^^^^^
86+
87+
type FirstParameter<T> = T extends (x: infer P) => unknown ? P : unknown
88+
>FirstParameter : FirstParameter<T>
89+
> : ^^^^^^^^^^^^^^^^^
90+
>x : P
91+
> : ^
92+
93+
type X = FirstParameter<typeof h>['foo']
94+
>X : unknown
95+
> : ^^^^^^^
96+
>h : <T extends unknown = string>(x: { foo: T; }) => unknown
97+
> : ^ ^^^^^^^^^ ^^^^^^^^^^^ ^^^^^^^^^ ^^^^^^^^
98+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// @strict: true
2+
// @noEmit: true
3+
4+
// https://github.com/microsoft/TypeScript/issues/59490
5+
6+
type ComponentProps<T> = T extends (props: infer P) => unknown ? P : never;
7+
8+
declare function wrapComponent<P>(
9+
component: (props: P) => unknown,
10+
): (props: P) => unknown;
11+
12+
const WrappedComponent = wrapComponent(
13+
<T extends string = "span">(props: {
14+
as?: T | undefined;
15+
className?: string;
16+
}) => {
17+
return null;
18+
},
19+
);
20+
21+
type RetrievedProps = ComponentProps<typeof WrappedComponent>;
22+
23+
declare const f: <T>(f: (x: T) => unknown) => (x: T) => unknown
24+
declare const g: <T extends unknown = string>(x: { foo: T }) => unknown
25+
26+
const h = f(g)
27+
28+
type FirstParameter<T> = T extends (x: infer P) => unknown ? P : unknown
29+
type X = FirstParameter<typeof h>['foo']

0 commit comments

Comments
 (0)