这是设计使然。它总是返回最后一个重载的签名。看到这个issue/28789
但是,还有另一种方法。
请记住,重载只是函数类型的交集。
我们可以声明一个类型来保存我们所有的重载签名:
type Signatures = {
1: (x: string) => number,
2: (x: string, y: number) => 42
3: (x: number) => string
}
现在,为了创建重载,我们需要获取所有对象属性的并集并将它们相交。
// credits goes to https://stackoverflow.com/a/50375286
type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (
k: infer I
) => void
? I
: never;
type Values<T> = T[keyof T]
type Overloading = UnionToIntersection<Values<Signatures>>
它按预期工作:
declare const foo: Overloading;
const a = foo(123); // string
const b = foo('123'); // number
const c = foo('123', 456); // 42
现在,很容易获得所有允许参数的并集:
// [x: string] | [x: string, y: number] | [x: number]
type fooArgs = Parameters<Values<Signatures>>;
declare function bar(...args: fooArgs): string[]
const x = bar(123); // string[]
const y = bar('123'); // string[]
const z = bar('123', 456); // string[]
完整代码:
type Signatures = {
1: (x: string) => number,
2: (x: string, y: number) => 42
3: (x: number) => string
}
// credits goes to https://stackoverflow.com/a/50375286
type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (
k: infer I
) => void
? I
: never;
type Values<T> = T[keyof T]
type Overloading = UnionToIntersection<Values<Signatures>>
declare const foo: Overloading;
const a = foo(123); // string
const b = foo('123'); // number
const c = foo('123', 456); // 42
// [x: string] | [x: string, y: number] | [x: number]
type fooArgs = Parameters<Values<Signatures>>;
declare function bar(...args: fooArgs): string[]
const x = bar(123); // string[]
const y = bar('123'); // string[]
const z = bar('123', 456); // string[]
Playground