考虑以下示例:
class A {
private constructor(public n: number) {}
public getDouble() {
return this.n * 2;
}
static from(s: string): A;
static from(n: number): A;
static from(n1: number, n2: number): A;
static from(...args: unknown[]): A {
if (args.length === 1) {
if (typeof args[0] === 'string') {
if (args[0].length !== 1) {
throw new Error('String must have a length of 1')
}
return new A(Number(args[0]));
} else if (typeof args[0] === 'number') {
if (args[0] > 9) {
throw new Error('Number must be lower than 10')
}
return new A(args[0]);
}
} else if (args.length === 2) {
if (typeof args[0] === 'number' && typeof args[1] === 'number') {
const sum = args[0] + args[1];
if (sum > 9) {
throw new Error('Sum of numbers must be lower than 10')
}
return new A(sum);
}
}
throw new Error('No overload matched')
}
}
Run Code Online (Sandbox Code Playgroud)
的实例A只能使用静态方法 构造from,该方法被重载以获取字符串、数字或两个数字。有效参数仅包括长度为 1 的字符串、小于 10 的数字以及总和小于 10 的数字对 - 其他参数会导致错误。
我想实现另一个静态方法,它将检查是否可以从给定的参数列表构造validate的实例,如下所示:A
static validate(...args: Parameters<typeof A.from>): boolean {
try {
A.from(...args);
return true;
} catch (error) {
return false;
}
}
Run Code Online (Sandbox Code Playgroud)
问题在于Parameters<typeof A.from>解析为列表中最后一个重载的参数(在本例中为 )n1: number, n2: number,这会导致 TypeScript 不允许使用任何其他重载签名(即 )进行调用A.validate('foo')。
我怎样才能让 TypeScript 理解validate可以使用与 相同的重载签名来调用from?
我找到了两种可能的解决方案,但都有很大的缺点:
...args: unknown[]. 然而,这会让 TypeScript 认为from实际上可以使用任何参数来调用,而实际上它不能。from重载签名并声明它们validate。同样,难以维护 - 实际用例涉及更多的重载以及多个模仿from重载的静态方法,这将导致 50 多行重载声明。还有其他方法可以解决这个问题吗?有没有办法写一个OverloadParameters类型?
如果您有一个重载函数/方法,其中每个调用签名都具有相同的返回类型from()(返回类型始终为的情况A),则可以将该函数重构为具有单个调用签名的版本,其中包含剩余参数,其类型是剩余元组的并集:
static from(...args: [s: string] | [n: number] | [n1: number, n2: number]): A {\n // same impl as before\n} \nRun Code Online (Sandbox Code Playgroud)\n这可以像以前一样调用:
\nA.from("okay"); // works\nA.from(1); // okay\nA.from(2, 4); // okay\nA.from("oops", 2); // error!\nRun Code Online (Sandbox Code Playgroud)\n事实上,从 IntelliSense 的角度来看,它甚至看起来像是一个重载函数:
\n/* A.from(\xe2\x8e\x80) */\n// 1/3 from(s: string): A\n// 2/3 from(n: number): A\n// 3/3 from(n1: number, n2: number): A\nRun Code Online (Sandbox Code Playgroud)\n但至关重要的是,Parameters<typeof A["from"]>现在是元组的完整并集,并且不会丢失任何信息:
static validate(...args: Parameters<typeof A.from>): boolean {\n // same impl as before\n}\nRun Code Online (Sandbox Code Playgroud)\n您可以验证是否A.validate()可以通过与以下完全相同的方式调用A.from():
A.validate("okay"); // works\nA.validate(1); // okay\nA.validate(2, 4); // okay\nA.validate("oops", 2); // error!\nRun Code Online (Sandbox Code Playgroud)\n\n
| 归档时间: |
|
| 查看次数: |
1733 次 |
| 最近记录: |