Skip to content

Commit 31d0e8b

Browse files
committed
Prefer higher-priority inferences from generic signatures over low-priority inferences from the first pass
1 parent f2e9ebd commit 31d0e8b

File tree

4 files changed

+160
-5
lines changed

4 files changed

+160
-5
lines changed

src/compiler/checker.ts

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38973,7 +38973,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
3897338973
// potentially add inferred type parameters to the outer function return type.
3897438974
const returnType = context.signature && getReturnTypeOfSignature(context.signature);
3897538975
const returnSignature = returnType && getSingleCallOrConstructSignature(returnType);
38976-
if (returnSignature && !returnSignature.typeParameters && !every(context.inferences, hasInferenceCandidates)) {
38976+
if (returnSignature && !returnSignature.typeParameters && !every(context.inferences, info => hasInferenceCandidates(info) && info.priority === InferencePriority.None)) {
3897738977
// Instantiate the signature with its own type parameters as type arguments, possibly
3897838978
// renaming the type parameters to ensure they have unique names.
3897938979
const uniqueTypeParameters = getUniqueTypeParameters(context, signature.typeParameters);
@@ -38993,8 +38993,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
3899338993
// If the type parameters for which we produced candidates do not have any inferences yet,
3899438994
// we adopt the new inference candidates and add the type parameters of the expression type
3899538995
// to the set of inferred type parameters for the outer function return type.
38996-
if (!hasOverlappingInferences(context.inferences, inferences)) {
38997-
mergeInferences(context.inferences, inferences);
38996+
const merged = tryInferencesMerge(context.inferences, inferences);
38997+
if (merged) {
3899838998
context.inferredTypeParameters = concatenate(context.inferredTypeParameters, uniqueTypeParameters);
3899938999
return getOrCreateTypeFromSignature(instantiatedSignature);
3900039000
}
@@ -39034,12 +39034,19 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
3903439034
return false;
3903539035
}
3903639036

39037-
function mergeInferences(target: InferenceInfo[], source: InferenceInfo[]) {
39037+
function tryInferencesMerge(target: InferenceInfo[], source: InferenceInfo[]) {
39038+
let merged = false;
39039+
39040+
const areOverlapping = hasOverlappingInferences(target, source);
39041+
3903839042
for (let i = 0; i < target.length; i++) {
39039-
if (!hasInferenceCandidates(target[i]) && hasInferenceCandidates(source[i])) {
39043+
if (areOverlapping ? hasInferenceCandidates(source[i]) && hasInferenceCandidates(target[i]) && source[i].priority! < (target[i].priority! & ~InferencePriority.ReturnType) : hasInferenceCandidates(source[i])) {
3904039044
target[i] = source[i];
39045+
target[i].priority = InferencePriority.None;
39046+
merged = true;
3904139047
}
3904239048
}
39049+
return merged;
3904339050
}
3904439051

3904539052
function getUniqueTypeParameters(context: InferenceContext, typeParameters: readonly TypeParameter[]): readonly TypeParameter[] {
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
//// [tests/cases/compiler/genericFunctionInference3.ts] ////
2+
3+
=== genericFunctionInference3.ts ===
4+
// https://github.com/microsoft/TypeScript/issues/56931
5+
6+
declare function defineComponent<Props extends Record<string, any>>(
7+
>defineComponent : Symbol(defineComponent, Decl(genericFunctionInference3.ts, 0, 0))
8+
>Props : Symbol(Props, Decl(genericFunctionInference3.ts, 2, 33))
9+
>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --))
10+
11+
setup: (props: Props) => void,
12+
>setup : Symbol(setup, Decl(genericFunctionInference3.ts, 2, 68))
13+
>props : Symbol(props, Decl(genericFunctionInference3.ts, 3, 10))
14+
>Props : Symbol(Props, Decl(genericFunctionInference3.ts, 2, 33))
15+
16+
options?: {
17+
>options : Symbol(options, Decl(genericFunctionInference3.ts, 3, 32))
18+
19+
props?: (keyof Props)[];
20+
>props : Symbol(props, Decl(genericFunctionInference3.ts, 4, 13))
21+
>Props : Symbol(Props, Decl(genericFunctionInference3.ts, 2, 33))
22+
23+
},
24+
): (props: Props) => unknown;
25+
>props : Symbol(props, Decl(genericFunctionInference3.ts, 7, 4))
26+
>Props : Symbol(Props, Decl(genericFunctionInference3.ts, 2, 33))
27+
28+
const res1 = defineComponent(
29+
>res1 : Symbol(res1, Decl(genericFunctionInference3.ts, 9, 5))
30+
>defineComponent : Symbol(defineComponent, Decl(genericFunctionInference3.ts, 0, 0))
31+
32+
<T extends string>(_props: { msg: T }) => {
33+
>T : Symbol(T, Decl(genericFunctionInference3.ts, 10, 3))
34+
>_props : Symbol(_props, Decl(genericFunctionInference3.ts, 10, 21))
35+
>msg : Symbol(msg, Decl(genericFunctionInference3.ts, 10, 30))
36+
>T : Symbol(T, Decl(genericFunctionInference3.ts, 10, 3))
37+
38+
return () => {};
39+
}
40+
);
41+
42+
const res2 = defineComponent(
43+
>res2 : Symbol(res2, Decl(genericFunctionInference3.ts, 15, 5))
44+
>defineComponent : Symbol(defineComponent, Decl(genericFunctionInference3.ts, 0, 0))
45+
46+
<T extends string>(_props: { msg: T }) => {
47+
>T : Symbol(T, Decl(genericFunctionInference3.ts, 16, 3))
48+
>_props : Symbol(_props, Decl(genericFunctionInference3.ts, 16, 21))
49+
>msg : Symbol(msg, Decl(genericFunctionInference3.ts, 16, 30))
50+
>T : Symbol(T, Decl(genericFunctionInference3.ts, 16, 3))
51+
52+
return () => {};
53+
},
54+
{
55+
props: ["msg"],
56+
>props : Symbol(props, Decl(genericFunctionInference3.ts, 19, 3))
57+
58+
},
59+
);
60+
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
//// [tests/cases/compiler/genericFunctionInference3.ts] ////
2+
3+
=== genericFunctionInference3.ts ===
4+
// https://github.com/microsoft/TypeScript/issues/56931
5+
6+
declare function defineComponent<Props extends Record<string, any>>(
7+
>defineComponent : <Props extends Record<string, any>>(setup: (props: Props) => void, options?: { props?: (keyof Props)[];}) => (props: Props) => unknown
8+
9+
setup: (props: Props) => void,
10+
>setup : (props: Props) => void
11+
>props : Props
12+
13+
options?: {
14+
>options : { props?: (keyof Props)[] | undefined; } | undefined
15+
16+
props?: (keyof Props)[];
17+
>props : (keyof Props)[] | undefined
18+
19+
},
20+
): (props: Props) => unknown;
21+
>props : Props
22+
23+
const res1 = defineComponent(
24+
>res1 : <T extends string>(props: { msg: T; }) => unknown
25+
>defineComponent( <T extends string>(_props: { msg: T }) => { return () => {}; }) : <T extends string>(props: { msg: T; }) => unknown
26+
>defineComponent : <Props extends Record<string, any>>(setup: (props: Props) => void, options?: { props?: (keyof Props)[] | undefined; } | undefined) => (props: Props) => unknown
27+
28+
<T extends string>(_props: { msg: T }) => {
29+
><T extends string>(_props: { msg: T }) => { return () => {}; } : <T extends string>(_props: { msg: T;}) => () => void
30+
>_props : { msg: T; }
31+
>msg : T
32+
33+
return () => {};
34+
>() => {} : () => void
35+
}
36+
);
37+
38+
const res2 = defineComponent(
39+
>res2 : <T extends string>(props: { msg: T; }) => unknown
40+
>defineComponent( <T extends string>(_props: { msg: T }) => { return () => {}; }, { props: ["msg"], },) : <T extends string>(props: { msg: T; }) => unknown
41+
>defineComponent : <Props extends Record<string, any>>(setup: (props: Props) => void, options?: { props?: (keyof Props)[] | undefined; } | undefined) => (props: Props) => unknown
42+
43+
<T extends string>(_props: { msg: T }) => {
44+
><T extends string>(_props: { msg: T }) => { return () => {}; } : <T extends string>(_props: { msg: T;}) => () => void
45+
>_props : { msg: T; }
46+
>msg : T
47+
48+
return () => {};
49+
>() => {} : () => void
50+
51+
},
52+
{
53+
>{ props: ["msg"], } : { props: "msg"[]; }
54+
55+
props: ["msg"],
56+
>props : "msg"[]
57+
>["msg"] : "msg"[]
58+
>"msg" : "msg"
59+
60+
},
61+
);
62+
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// @strict: true
2+
// @noEmit: true
3+
4+
// https://github.com/microsoft/TypeScript/issues/56931
5+
6+
declare function defineComponent<Props extends Record<string, any>>(
7+
setup: (props: Props) => void,
8+
options?: {
9+
props?: (keyof Props)[];
10+
},
11+
): (props: Props) => unknown;
12+
13+
const res1 = defineComponent(
14+
<T extends string>(_props: { msg: T }) => {
15+
return () => {};
16+
}
17+
);
18+
19+
const res2 = defineComponent(
20+
<T extends string>(_props: { msg: T }) => {
21+
return () => {};
22+
},
23+
{
24+
props: ["msg"],
25+
},
26+
);

0 commit comments

Comments
 (0)