基本上我只是想包装一个具有多个签名的函数。有没有一种干净的方法可以做到这一点,而无需重新硬编码所有签名?我只想bar在下面接受任何相同的论点foo
declare function foo(x: string): number;
declare function foo(x: string, y: number): 42;
declare function foo(x: number): string;
type fooArgs = Parameters<typeof foo>; // this only extracts from the last signature
declare function bar(...args: fooArgs): string[]
const a = foo(123); // fine
const b = foo('123'); // fine
const c = foo('123', 456); // fine
const x = bar(123); // fine
const y = bar('123'); // fails because it expects (x: number) => string
const z = bar('123', 456); // fails
Run Code Online (Sandbox Code Playgroud)
这是设计使然。它总是返回最后一个重载的签名。参见本期/28789
然而,还有另一种方法。
请记住,重载只是函数类型的交集。
我们可以声明一个类型来保存所有的重载签名:
type Signatures = {
1: (x: string) => number,
2: (x: string, y: number) => 42
3: (x: number) => string
}
Run Code Online (Sandbox Code Playgroud)
现在,为了创建重载,我们需要获取所有对象属性的并集并将它们相交。
// 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>>
Run Code Online (Sandbox Code Playgroud)
它按预期工作:
declare const foo: Overloading;
const a = foo(123); // string
const b = foo('123'); // number
const c = foo('123', 456); // 42
Run Code Online (Sandbox Code Playgroud)
现在,很容易获得所有允许参数的并集:
// [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[]
Run Code Online (Sandbox Code Playgroud)
整个代码:
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[]
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
671 次 |
| 最近记录: |