mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-04 21:53:42 -06:00
Improve inference between types with multiple signatures (#54448)
Co-authored-by: Ryan Cavanaugh <RyanCavanaugh@users.noreply.github.com> Co-authored-by: TypeScript Bot <typescriptbot@microsoft.com>
This commit is contained in:
parent
d0684f789b
commit
6d07d5fa40
@ -25535,12 +25535,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
|
||||
function inferFromSignatures(source: Type, target: Type, kind: SignatureKind) {
|
||||
const sourceSignatures = getSignaturesOfType(source, kind);
|
||||
const targetSignatures = getSignaturesOfType(target, kind);
|
||||
const sourceLen = sourceSignatures.length;
|
||||
const targetLen = targetSignatures.length;
|
||||
const len = sourceLen < targetLen ? sourceLen : targetLen;
|
||||
for (let i = 0; i < len; i++) {
|
||||
inferFromSignature(getBaseSignature(sourceSignatures[sourceLen - len + i]), getErasedSignature(targetSignatures[targetLen - len + i]));
|
||||
if (sourceLen > 0) {
|
||||
// We match source and target signatures from the bottom up, and if the source has fewer signatures
|
||||
// than the target, we infer from the first source signature to the excess target signatures.
|
||||
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]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
203
tests/baselines/reference/multiSignatureTypeInference.symbols
Normal file
203
tests/baselines/reference/multiSignatureTypeInference.symbols
Normal file
@ -0,0 +1,203 @@
|
||||
//// [tests/cases/compiler/multiSignatureTypeInference.ts] ////
|
||||
|
||||
=== multiSignatureTypeInference.ts ===
|
||||
declare function f1(arg: boolean): string;
|
||||
>f1 : Symbol(f1, Decl(multiSignatureTypeInference.ts, 0, 0), Decl(multiSignatureTypeInference.ts, 0, 42), Decl(multiSignatureTypeInference.ts, 1, 56))
|
||||
>arg : Symbol(arg, Decl(multiSignatureTypeInference.ts, 0, 20))
|
||||
|
||||
declare function f1(arg1: number, arg2: number): number;
|
||||
>f1 : Symbol(f1, Decl(multiSignatureTypeInference.ts, 0, 0), Decl(multiSignatureTypeInference.ts, 0, 42), Decl(multiSignatureTypeInference.ts, 1, 56))
|
||||
>arg1 : Symbol(arg1, Decl(multiSignatureTypeInference.ts, 1, 20))
|
||||
>arg2 : Symbol(arg2, Decl(multiSignatureTypeInference.ts, 1, 33))
|
||||
|
||||
declare function f1(...args: string[]): string[];
|
||||
>f1 : Symbol(f1, Decl(multiSignatureTypeInference.ts, 0, 0), Decl(multiSignatureTypeInference.ts, 0, 42), Decl(multiSignatureTypeInference.ts, 1, 56))
|
||||
>args : Symbol(args, Decl(multiSignatureTypeInference.ts, 2, 20))
|
||||
|
||||
declare function f2(arg: unknown): unknown;
|
||||
>f2 : Symbol(f2, Decl(multiSignatureTypeInference.ts, 2, 49))
|
||||
>arg : Symbol(arg, Decl(multiSignatureTypeInference.ts, 4, 20))
|
||||
|
||||
declare function f3(): string;
|
||||
>f3 : Symbol(f3, Decl(multiSignatureTypeInference.ts, 4, 43))
|
||||
|
||||
type AllParams<T> =
|
||||
>AllParams : Symbol(AllParams, Decl(multiSignatureTypeInference.ts, 6, 30))
|
||||
>T : Symbol(T, Decl(multiSignatureTypeInference.ts, 8, 15))
|
||||
|
||||
T extends { (...a: infer A1): any, (...a: infer A2): any, (...a: infer A3): any, (...a: infer A4): any } ? A1 | A2 | A3 | A4 : never;
|
||||
>T : Symbol(T, Decl(multiSignatureTypeInference.ts, 8, 15))
|
||||
>a : Symbol(a, Decl(multiSignatureTypeInference.ts, 9, 17))
|
||||
>A1 : Symbol(A1, Decl(multiSignatureTypeInference.ts, 9, 28))
|
||||
>a : Symbol(a, Decl(multiSignatureTypeInference.ts, 9, 40))
|
||||
>A2 : Symbol(A2, Decl(multiSignatureTypeInference.ts, 9, 51))
|
||||
>a : Symbol(a, Decl(multiSignatureTypeInference.ts, 9, 63))
|
||||
>A3 : Symbol(A3, Decl(multiSignatureTypeInference.ts, 9, 74))
|
||||
>a : Symbol(a, Decl(multiSignatureTypeInference.ts, 9, 86))
|
||||
>A4 : Symbol(A4, Decl(multiSignatureTypeInference.ts, 9, 97))
|
||||
>A1 : Symbol(A1, Decl(multiSignatureTypeInference.ts, 9, 28))
|
||||
>A2 : Symbol(A2, Decl(multiSignatureTypeInference.ts, 9, 51))
|
||||
>A3 : Symbol(A3, Decl(multiSignatureTypeInference.ts, 9, 74))
|
||||
>A4 : Symbol(A4, Decl(multiSignatureTypeInference.ts, 9, 97))
|
||||
|
||||
type AllReturns<T> =
|
||||
>AllReturns : Symbol(AllReturns, Decl(multiSignatureTypeInference.ts, 9, 137))
|
||||
>T : Symbol(T, Decl(multiSignatureTypeInference.ts, 11, 16))
|
||||
|
||||
T extends { (...a: any[]): infer R1, (...a: any[]): infer R2, (...a: any[]): infer R3, (...a: any[]): infer R4 } ? R1 | R2 | R3 | R4 : never;
|
||||
>T : Symbol(T, Decl(multiSignatureTypeInference.ts, 11, 16))
|
||||
>a : Symbol(a, Decl(multiSignatureTypeInference.ts, 12, 17))
|
||||
>R1 : Symbol(R1, Decl(multiSignatureTypeInference.ts, 12, 36))
|
||||
>a : Symbol(a, Decl(multiSignatureTypeInference.ts, 12, 42))
|
||||
>R2 : Symbol(R2, Decl(multiSignatureTypeInference.ts, 12, 61))
|
||||
>a : Symbol(a, Decl(multiSignatureTypeInference.ts, 12, 67))
|
||||
>R3 : Symbol(R3, Decl(multiSignatureTypeInference.ts, 12, 86))
|
||||
>a : Symbol(a, Decl(multiSignatureTypeInference.ts, 12, 92))
|
||||
>R4 : Symbol(R4, Decl(multiSignatureTypeInference.ts, 12, 111))
|
||||
>R1 : Symbol(R1, Decl(multiSignatureTypeInference.ts, 12, 36))
|
||||
>R2 : Symbol(R2, Decl(multiSignatureTypeInference.ts, 12, 61))
|
||||
>R3 : Symbol(R3, Decl(multiSignatureTypeInference.ts, 12, 86))
|
||||
>R4 : Symbol(R4, Decl(multiSignatureTypeInference.ts, 12, 111))
|
||||
|
||||
type Params1 = AllParams<typeof f1>; // string[] | [arg: boolean] | [arg1: number, arg2: number]
|
||||
>Params1 : Symbol(Params1, Decl(multiSignatureTypeInference.ts, 12, 145))
|
||||
>AllParams : Symbol(AllParams, Decl(multiSignatureTypeInference.ts, 6, 30))
|
||||
>f1 : Symbol(f1, Decl(multiSignatureTypeInference.ts, 0, 0), Decl(multiSignatureTypeInference.ts, 0, 42), Decl(multiSignatureTypeInference.ts, 1, 56))
|
||||
|
||||
type Params2 = AllParams<typeof f2>; // [arg: unknown]
|
||||
>Params2 : Symbol(Params2, Decl(multiSignatureTypeInference.ts, 14, 36))
|
||||
>AllParams : Symbol(AllParams, Decl(multiSignatureTypeInference.ts, 6, 30))
|
||||
>f2 : Symbol(f2, Decl(multiSignatureTypeInference.ts, 2, 49))
|
||||
|
||||
type Params3 = AllParams<typeof f3>; // []
|
||||
>Params3 : Symbol(Params3, Decl(multiSignatureTypeInference.ts, 15, 36))
|
||||
>AllParams : Symbol(AllParams, Decl(multiSignatureTypeInference.ts, 6, 30))
|
||||
>f3 : Symbol(f3, Decl(multiSignatureTypeInference.ts, 4, 43))
|
||||
|
||||
type Returns1 = AllReturns<typeof f1> // string | number | string[]
|
||||
>Returns1 : Symbol(Returns1, Decl(multiSignatureTypeInference.ts, 16, 36))
|
||||
>AllReturns : Symbol(AllReturns, Decl(multiSignatureTypeInference.ts, 9, 137))
|
||||
>f1 : Symbol(f1, Decl(multiSignatureTypeInference.ts, 0, 0), Decl(multiSignatureTypeInference.ts, 0, 42), Decl(multiSignatureTypeInference.ts, 1, 56))
|
||||
|
||||
type Returns2 = AllReturns<typeof f2>; // unknown
|
||||
>Returns2 : Symbol(Returns2, Decl(multiSignatureTypeInference.ts, 18, 37))
|
||||
>AllReturns : Symbol(AllReturns, Decl(multiSignatureTypeInference.ts, 9, 137))
|
||||
>f2 : Symbol(f2, Decl(multiSignatureTypeInference.ts, 2, 49))
|
||||
|
||||
type Returns3 = AllReturns<typeof f3>; // string
|
||||
>Returns3 : Symbol(Returns3, Decl(multiSignatureTypeInference.ts, 19, 38))
|
||||
>AllReturns : Symbol(AllReturns, Decl(multiSignatureTypeInference.ts, 9, 137))
|
||||
>f3 : Symbol(f3, Decl(multiSignatureTypeInference.ts, 4, 43))
|
||||
|
||||
// Repro from #28867
|
||||
|
||||
type InferTwoOverloads<F extends Function> =
|
||||
>InferTwoOverloads : Symbol(InferTwoOverloads, Decl(multiSignatureTypeInference.ts, 20, 38))
|
||||
>F : Symbol(F, Decl(multiSignatureTypeInference.ts, 24, 23))
|
||||
>Function : Symbol(Function, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
|
||||
|
||||
F extends { (...a1: infer A1): infer R1, (...a0: infer A0): infer R0 } ?
|
||||
>F : Symbol(F, Decl(multiSignatureTypeInference.ts, 24, 23))
|
||||
>a1 : Symbol(a1, Decl(multiSignatureTypeInference.ts, 25, 15))
|
||||
>A1 : Symbol(A1, Decl(multiSignatureTypeInference.ts, 25, 27))
|
||||
>R1 : Symbol(R1, Decl(multiSignatureTypeInference.ts, 25, 38))
|
||||
>a0 : Symbol(a0, Decl(multiSignatureTypeInference.ts, 25, 44))
|
||||
>A0 : Symbol(A0, Decl(multiSignatureTypeInference.ts, 25, 56))
|
||||
>R0 : Symbol(R0, Decl(multiSignatureTypeInference.ts, 25, 67))
|
||||
|
||||
[(...a1: A1) => R1, (...a0: A0) => R0] :
|
||||
>a1 : Symbol(a1, Decl(multiSignatureTypeInference.ts, 26, 6))
|
||||
>A1 : Symbol(A1, Decl(multiSignatureTypeInference.ts, 25, 27))
|
||||
>R1 : Symbol(R1, Decl(multiSignatureTypeInference.ts, 25, 38))
|
||||
>a0 : Symbol(a0, Decl(multiSignatureTypeInference.ts, 26, 25))
|
||||
>A0 : Symbol(A0, Decl(multiSignatureTypeInference.ts, 25, 56))
|
||||
>R0 : Symbol(R0, Decl(multiSignatureTypeInference.ts, 25, 67))
|
||||
|
||||
never;
|
||||
|
||||
type Expected = InferTwoOverloads<((x: string) => number) & (() => string)>; // [(x: string) => number, () => string]
|
||||
>Expected : Symbol(Expected, Decl(multiSignatureTypeInference.ts, 27, 10))
|
||||
>InferTwoOverloads : Symbol(InferTwoOverloads, Decl(multiSignatureTypeInference.ts, 20, 38))
|
||||
>x : Symbol(x, Decl(multiSignatureTypeInference.ts, 29, 36))
|
||||
|
||||
type JustOneSignature = InferTwoOverloads<((x: string) => number)>; // [(x: string) => number, (x: string) => number]
|
||||
>JustOneSignature : Symbol(JustOneSignature, Decl(multiSignatureTypeInference.ts, 29, 76))
|
||||
>InferTwoOverloads : Symbol(InferTwoOverloads, Decl(multiSignatureTypeInference.ts, 20, 38))
|
||||
>x : Symbol(x, Decl(multiSignatureTypeInference.ts, 31, 44))
|
||||
|
||||
type JustTheOtherSignature = InferTwoOverloads<(() => string)>; // [() => string, () => string]
|
||||
>JustTheOtherSignature : Symbol(JustTheOtherSignature, Decl(multiSignatureTypeInference.ts, 31, 67))
|
||||
>InferTwoOverloads : Symbol(InferTwoOverloads, Decl(multiSignatureTypeInference.ts, 20, 38))
|
||||
|
||||
// Repro from #28867
|
||||
|
||||
type Overloads<F> =
|
||||
>Overloads : Symbol(Overloads, Decl(multiSignatureTypeInference.ts, 33, 63))
|
||||
>F : Symbol(F, Decl(multiSignatureTypeInference.ts, 37, 15))
|
||||
|
||||
F extends {
|
||||
>F : Symbol(F, Decl(multiSignatureTypeInference.ts, 37, 15))
|
||||
|
||||
(...args: infer A1): infer R1
|
||||
>args : Symbol(args, Decl(multiSignatureTypeInference.ts, 39, 11))
|
||||
>A1 : Symbol(A1, Decl(multiSignatureTypeInference.ts, 39, 25))
|
||||
>R1 : Symbol(R1, Decl(multiSignatureTypeInference.ts, 39, 36))
|
||||
|
||||
(...args: infer A2): infer R2;
|
||||
>args : Symbol(args, Decl(multiSignatureTypeInference.ts, 40, 11))
|
||||
>A2 : Symbol(A2, Decl(multiSignatureTypeInference.ts, 40, 25))
|
||||
>R2 : Symbol(R2, Decl(multiSignatureTypeInference.ts, 40, 36))
|
||||
|
||||
} ? {rule: 2, variants: [A1, R1] | [A2, R2]} :
|
||||
>rule : Symbol(rule, Decl(multiSignatureTypeInference.ts, 41, 11))
|
||||
>variants : Symbol(variants, Decl(multiSignatureTypeInference.ts, 41, 19))
|
||||
>A1 : Symbol(A1, Decl(multiSignatureTypeInference.ts, 39, 25))
|
||||
>R1 : Symbol(R1, Decl(multiSignatureTypeInference.ts, 39, 36))
|
||||
>A2 : Symbol(A2, Decl(multiSignatureTypeInference.ts, 40, 25))
|
||||
>R2 : Symbol(R2, Decl(multiSignatureTypeInference.ts, 40, 36))
|
||||
|
||||
F extends {
|
||||
>F : Symbol(F, Decl(multiSignatureTypeInference.ts, 37, 15))
|
||||
|
||||
(...args: infer A1): infer R1;
|
||||
>args : Symbol(args, Decl(multiSignatureTypeInference.ts, 43, 11))
|
||||
>A1 : Symbol(A1, Decl(multiSignatureTypeInference.ts, 43, 25))
|
||||
>R1 : Symbol(R1, Decl(multiSignatureTypeInference.ts, 43, 36))
|
||||
|
||||
} ? {rule: 1, variants: [A1, R1]} :
|
||||
>rule : Symbol(rule, Decl(multiSignatureTypeInference.ts, 44, 11))
|
||||
>variants : Symbol(variants, Decl(multiSignatureTypeInference.ts, 44, 19))
|
||||
>A1 : Symbol(A1, Decl(multiSignatureTypeInference.ts, 43, 25))
|
||||
>R1 : Symbol(R1, Decl(multiSignatureTypeInference.ts, 43, 36))
|
||||
|
||||
never;
|
||||
|
||||
declare const ok1: Overloads<(x: number) => boolean>; // {rule: 2, variants: [[number], boolean]}
|
||||
>ok1 : Symbol(ok1, Decl(multiSignatureTypeInference.ts, 47, 13))
|
||||
>Overloads : Symbol(Overloads, Decl(multiSignatureTypeInference.ts, 33, 63))
|
||||
>x : Symbol(x, Decl(multiSignatureTypeInference.ts, 47, 30))
|
||||
|
||||
declare const ok2: Overloads<{(): 1; (x: number): 2}>; // {rule: 2, variants: [[], 1] | [[number], 2]}
|
||||
>ok2 : Symbol(ok2, Decl(multiSignatureTypeInference.ts, 49, 13))
|
||||
>Overloads : Symbol(Overloads, Decl(multiSignatureTypeInference.ts, 33, 63))
|
||||
>x : Symbol(x, Decl(multiSignatureTypeInference.ts, 49, 38))
|
||||
|
||||
declare const ok3: Overloads<() => boolean>; // {rule: 2, variants: [[], boolean] }
|
||||
>ok3 : Symbol(ok3, Decl(multiSignatureTypeInference.ts, 51, 13))
|
||||
>Overloads : Symbol(Overloads, Decl(multiSignatureTypeInference.ts, 33, 63))
|
||||
|
||||
declare const ok4: Overloads<(...args: unknown[]) => boolean>; // {rule: 2, variants: [unknown[], boolean] }
|
||||
>ok4 : Symbol(ok4, Decl(multiSignatureTypeInference.ts, 53, 13))
|
||||
>Overloads : Symbol(Overloads, Decl(multiSignatureTypeInference.ts, 33, 63))
|
||||
>args : Symbol(args, Decl(multiSignatureTypeInference.ts, 53, 30))
|
||||
|
||||
declare const ok5: Overloads<(x: unknown) => boolean>; // {rule: 2, variants: [[unknown], boolean] }
|
||||
>ok5 : Symbol(ok5, Decl(multiSignatureTypeInference.ts, 55, 13))
|
||||
>Overloads : Symbol(Overloads, Decl(multiSignatureTypeInference.ts, 33, 63))
|
||||
>x : Symbol(x, Decl(multiSignatureTypeInference.ts, 55, 30))
|
||||
|
||||
declare const ok6: Overloads<(x: any) => boolean>; // {rule: 2, variants: [[any], boolean] }
|
||||
>ok6 : Symbol(ok6, Decl(multiSignatureTypeInference.ts, 57, 13))
|
||||
>Overloads : Symbol(Overloads, Decl(multiSignatureTypeInference.ts, 33, 63))
|
||||
>x : Symbol(x, Decl(multiSignatureTypeInference.ts, 57, 30))
|
||||
|
||||
140
tests/baselines/reference/multiSignatureTypeInference.types
Normal file
140
tests/baselines/reference/multiSignatureTypeInference.types
Normal file
@ -0,0 +1,140 @@
|
||||
//// [tests/cases/compiler/multiSignatureTypeInference.ts] ////
|
||||
|
||||
=== multiSignatureTypeInference.ts ===
|
||||
declare function f1(arg: boolean): string;
|
||||
>f1 : { (arg: boolean): string; (arg1: number, arg2: number): number; (...args: string[]): string[]; }
|
||||
>arg : boolean
|
||||
|
||||
declare function f1(arg1: number, arg2: number): number;
|
||||
>f1 : { (arg: boolean): string; (arg1: number, arg2: number): number; (...args: string[]): string[]; }
|
||||
>arg1 : number
|
||||
>arg2 : number
|
||||
|
||||
declare function f1(...args: string[]): string[];
|
||||
>f1 : { (arg: boolean): string; (arg1: number, arg2: number): number; (...args: string[]): string[]; }
|
||||
>args : string[]
|
||||
|
||||
declare function f2(arg: unknown): unknown;
|
||||
>f2 : (arg: unknown) => unknown
|
||||
>arg : unknown
|
||||
|
||||
declare function f3(): string;
|
||||
>f3 : () => string
|
||||
|
||||
type AllParams<T> =
|
||||
>AllParams : AllParams<T>
|
||||
|
||||
T extends { (...a: infer A1): any, (...a: infer A2): any, (...a: infer A3): any, (...a: infer A4): any } ? A1 | A2 | A3 | A4 : never;
|
||||
>a : A1
|
||||
>a : A2
|
||||
>a : A3
|
||||
>a : A4
|
||||
|
||||
type AllReturns<T> =
|
||||
>AllReturns : AllReturns<T>
|
||||
|
||||
T extends { (...a: any[]): infer R1, (...a: any[]): infer R2, (...a: any[]): infer R3, (...a: any[]): infer R4 } ? R1 | R2 | R3 | R4 : never;
|
||||
>a : any[]
|
||||
>a : any[]
|
||||
>a : any[]
|
||||
>a : any[]
|
||||
|
||||
type Params1 = AllParams<typeof f1>; // string[] | [arg: boolean] | [arg1: number, arg2: number]
|
||||
>Params1 : string[] | [arg: boolean] | [arg1: number, arg2: number]
|
||||
>f1 : { (arg: boolean): string; (arg1: number, arg2: number): number; (...args: string[]): string[]; }
|
||||
|
||||
type Params2 = AllParams<typeof f2>; // [arg: unknown]
|
||||
>Params2 : [arg: unknown]
|
||||
>f2 : (arg: unknown) => unknown
|
||||
|
||||
type Params3 = AllParams<typeof f3>; // []
|
||||
>Params3 : []
|
||||
>f3 : () => string
|
||||
|
||||
type Returns1 = AllReturns<typeof f1> // string | number | string[]
|
||||
>Returns1 : string | number | string[]
|
||||
>f1 : { (arg: boolean): string; (arg1: number, arg2: number): number; (...args: string[]): string[]; }
|
||||
|
||||
type Returns2 = AllReturns<typeof f2>; // unknown
|
||||
>Returns2 : unknown
|
||||
>f2 : (arg: unknown) => unknown
|
||||
|
||||
type Returns3 = AllReturns<typeof f3>; // string
|
||||
>Returns3 : string
|
||||
>f3 : () => string
|
||||
|
||||
// Repro from #28867
|
||||
|
||||
type InferTwoOverloads<F extends Function> =
|
||||
>InferTwoOverloads : InferTwoOverloads<F>
|
||||
|
||||
F extends { (...a1: infer A1): infer R1, (...a0: infer A0): infer R0 } ?
|
||||
>a1 : A1
|
||||
>a0 : A0
|
||||
|
||||
[(...a1: A1) => R1, (...a0: A0) => R0] :
|
||||
>a1 : A1
|
||||
>a0 : A0
|
||||
|
||||
never;
|
||||
|
||||
type Expected = InferTwoOverloads<((x: string) => number) & (() => string)>; // [(x: string) => number, () => string]
|
||||
>Expected : [(x: string) => number, () => string]
|
||||
>x : string
|
||||
|
||||
type JustOneSignature = InferTwoOverloads<((x: string) => number)>; // [(x: string) => number, (x: string) => number]
|
||||
>JustOneSignature : [(x: string) => number, (x: string) => number]
|
||||
>x : string
|
||||
|
||||
type JustTheOtherSignature = InferTwoOverloads<(() => string)>; // [() => string, () => string]
|
||||
>JustTheOtherSignature : [() => string, () => string]
|
||||
|
||||
// Repro from #28867
|
||||
|
||||
type Overloads<F> =
|
||||
>Overloads : Overloads<F>
|
||||
|
||||
F extends {
|
||||
(...args: infer A1): infer R1
|
||||
>args : A1
|
||||
|
||||
(...args: infer A2): infer R2;
|
||||
>args : A2
|
||||
|
||||
} ? {rule: 2, variants: [A1, R1] | [A2, R2]} :
|
||||
>rule : 2
|
||||
>variants : [A1, R1] | [A2, R2]
|
||||
|
||||
F extends {
|
||||
(...args: infer A1): infer R1;
|
||||
>args : A1
|
||||
|
||||
} ? {rule: 1, variants: [A1, R1]} :
|
||||
>rule : 1
|
||||
>variants : [A1, R1]
|
||||
|
||||
never;
|
||||
|
||||
declare const ok1: Overloads<(x: number) => boolean>; // {rule: 2, variants: [[number], boolean]}
|
||||
>ok1 : { rule: 2; variants: [[x: number], boolean]; }
|
||||
>x : number
|
||||
|
||||
declare const ok2: Overloads<{(): 1; (x: number): 2}>; // {rule: 2, variants: [[], 1] | [[number], 2]}
|
||||
>ok2 : { rule: 2; variants: [[], 1] | [[x: number], 2]; }
|
||||
>x : number
|
||||
|
||||
declare const ok3: Overloads<() => boolean>; // {rule: 2, variants: [[], boolean] }
|
||||
>ok3 : { rule: 2; variants: [[], boolean]; }
|
||||
|
||||
declare const ok4: Overloads<(...args: unknown[]) => boolean>; // {rule: 2, variants: [unknown[], boolean] }
|
||||
>ok4 : { rule: 2; variants: [unknown[], boolean]; }
|
||||
>args : unknown[]
|
||||
|
||||
declare const ok5: Overloads<(x: unknown) => boolean>; // {rule: 2, variants: [[unknown], boolean] }
|
||||
>ok5 : { rule: 2; variants: [[x: unknown], boolean]; }
|
||||
>x : unknown
|
||||
|
||||
declare const ok6: Overloads<(x: any) => boolean>; // {rule: 2, variants: [[any], boolean] }
|
||||
>ok6 : { rule: 2; variants: [[x: any], boolean]; }
|
||||
>x : any
|
||||
|
||||
61
tests/cases/compiler/multiSignatureTypeInference.ts
Normal file
61
tests/cases/compiler/multiSignatureTypeInference.ts
Normal file
@ -0,0 +1,61 @@
|
||||
// @strict: true
|
||||
// @noEmit: true
|
||||
|
||||
declare function f1(arg: boolean): string;
|
||||
declare function f1(arg1: number, arg2: number): number;
|
||||
declare function f1(...args: string[]): string[];
|
||||
|
||||
declare function f2(arg: unknown): unknown;
|
||||
|
||||
declare function f3(): string;
|
||||
|
||||
type AllParams<T> =
|
||||
T extends { (...a: infer A1): any, (...a: infer A2): any, (...a: infer A3): any, (...a: infer A4): any } ? A1 | A2 | A3 | A4 : never;
|
||||
|
||||
type AllReturns<T> =
|
||||
T extends { (...a: any[]): infer R1, (...a: any[]): infer R2, (...a: any[]): infer R3, (...a: any[]): infer R4 } ? R1 | R2 | R3 | R4 : never;
|
||||
|
||||
type Params1 = AllParams<typeof f1>; // string[] | [arg: boolean] | [arg1: number, arg2: number]
|
||||
type Params2 = AllParams<typeof f2>; // [arg: unknown]
|
||||
type Params3 = AllParams<typeof f3>; // []
|
||||
|
||||
type Returns1 = AllReturns<typeof f1> // string | number | string[]
|
||||
type Returns2 = AllReturns<typeof f2>; // unknown
|
||||
type Returns3 = AllReturns<typeof f3>; // string
|
||||
|
||||
// Repro from #28867
|
||||
|
||||
type InferTwoOverloads<F extends Function> =
|
||||
F extends { (...a1: infer A1): infer R1, (...a0: infer A0): infer R0 } ?
|
||||
[(...a1: A1) => R1, (...a0: A0) => R0] :
|
||||
never;
|
||||
|
||||
type Expected = InferTwoOverloads<((x: string) => number) & (() => string)>; // [(x: string) => number, () => string]
|
||||
|
||||
type JustOneSignature = InferTwoOverloads<((x: string) => number)>; // [(x: string) => number, (x: string) => number]
|
||||
|
||||
type JustTheOtherSignature = InferTwoOverloads<(() => string)>; // [() => string, () => string]
|
||||
|
||||
// Repro from #28867
|
||||
|
||||
type Overloads<F> =
|
||||
F extends {
|
||||
(...args: infer A1): infer R1
|
||||
(...args: infer A2): infer R2;
|
||||
} ? {rule: 2, variants: [A1, R1] | [A2, R2]} :
|
||||
F extends {
|
||||
(...args: infer A1): infer R1;
|
||||
} ? {rule: 1, variants: [A1, R1]} :
|
||||
never;
|
||||
|
||||
declare const ok1: Overloads<(x: number) => boolean>; // {rule: 2, variants: [[number], boolean]}
|
||||
|
||||
declare const ok2: Overloads<{(): 1; (x: number): 2}>; // {rule: 2, variants: [[], 1] | [[number], 2]}
|
||||
|
||||
declare const ok3: Overloads<() => boolean>; // {rule: 2, variants: [[], boolean] }
|
||||
|
||||
declare const ok4: Overloads<(...args: unknown[]) => boolean>; // {rule: 2, variants: [unknown[], boolean] }
|
||||
|
||||
declare const ok5: Overloads<(x: unknown) => boolean>; // {rule: 2, variants: [[unknown], boolean] }
|
||||
|
||||
declare const ok6: Overloads<(x: any) => boolean>; // {rule: 2, variants: [[any], boolean] }
|
||||
Loading…
x
Reference in New Issue
Block a user