重载签名与函数实现不兼容没有意义



我有下面的代码,应该抛出一个打字错误:

export class Alpha {
getA(alpha: string | number);
getA(alpha: number) {
const beta = alpha * 2;
console.log(beta);
}
}
const a = new Alpha();
a.getA('1254s');

控制台的结果是NaN,因为在上面的示例中覆盖与实现BUT兼容实现不是与重写兼容,这导致TS不是提示我alpha实际上也可以是string,这导致我在代码中犯了这个错误。

是我错过了什么,还是它真的是TS的bug/限制?

在我看来,@aaronlukacs和@captain-yossarian的回答都没有抓住OP的重点。

OP声称通过编写这个实现:

async getA(alpha: number) {
const beta = alpha * 2;
console.log(beta);
}
由于超载签名getA(alpha: string | number), TypeScript没有提示alpha实际上也可能是一个字符串。因此,虽然这样调用函数:const result = a.getA('1254s');是完全有效的,但实现:const beta = alpha * 2;的这一行应该引发一个错误。

这似乎确实是TS在重载函数方面的限制,可以从您可以在文档中找到的几个建议中推断出来:

实现的签名从外部是不可见的。在编写重载函数时,应该始终使用两个或以上函数实现的更多签名

总是使用联合类型的形参,而不是重载可能的

符合这些建议的OP代码版本应该是这样的:

class Alpha {
getA(alpha: string): void;
getA(alpha: number): void;
getA(alpha: number | string): void {
const beta = alpha * 2;
console.log(beta);
}
}

确实在alpha * 2上引发错误,或者像这样:

class Alpha {
getA(alpha: number | string): void {
const beta = alpha * 2;
console.log(beta);
}
}

,其中重载完全被移除。

请注意,这两个版本并不完全等价:在第一个版本中,getA()不接受类型为string | number的值。

示例中的语法无效。你总是需要在重载中显式定义返回类型。

export class Alpha {
getA(alpha: string | number): void; // <--- return type should be defined
async getA(alpha: number) {
const beta = alpha * 2;
console.log(beta);
}
}
const a = new Alpha();
const result = await a.getA('1254s');

TypeScript允许你传递一个string,因为你在你的重载中允许它。

如果你不想允许string,只需删除重载。

Javascript函数重载与OOP语言有点不同,它只能通过名称和函数参数的数量来区分函数签名。

你没有重载函数,只是实现你的getA函数,就像你使用接口一样:

interface AlphaI{
getA(alpha: string | number): void;
}
class Alpha implements AlphaI{
getA(alpha: number) {
const beta = alpha * 2;
console.log(beta);
}
}
const a = new Alpha();
const result = a.getA('1254s');

函数的实现是有效的,因为number要么是数字,要么是字符串,但在这种情况下,TS抛出Argument of type 'string' is not assignable to parameter of type 'number'错误,因为它认为在类Alpha中实现。

相关内容

最新更新