【发布时间】:2019-08-12 06:44:45
【问题描述】:
我想使用 TypeScript 的重载功能创建一个函数,该函数根据传入的参数返回不同类型。我设法让它工作,但编译器无法在重载函数的实现中捕获错误.
下面的例子来自the TypeScript documentation(见下文)。该函数接受两种不同类型的参数:
-
object:期望返回类型number -
number:期望返回类型object
// With incompatible types
const suits = ["hearts", "spades", "clubs", "diamonds"];
function pickCard(x: { suit: string; card: number }[]): number;
function pickCard(x: number): { suit: string; card: number };
function pickCard(x): any {
if (typeof x == "object") {
let pickedCard = Math.floor(Math.random() * x.length);
// This part does not match the overload definition. The signature
// expect a `number` but we provide a `string`. The compiler does
// not throw an error in that case.
return pickedCard.toString();
} else if (typeof x == "number") {
let pickedSuit = Math.floor(x / 13);
return { suit: suits[pickedSuit], card: x % 13 };
}
}
const card = pickCard([{ suit: 'hearts', card: 5 }])
card.toFixed() // throw a runtime error: card.toFixed is not a function
// With compatible types
type Hand = { suit: string; card: number };
type HandWithScore = Hand & { score: number }
const suits = ["hearts", "spades", "clubs", "diamonds"];
function pickCard(x: Hand[]): HandWithScore;
function pickCard(x: number): Hand;
function pickCard(x): HandWithScore | Hand {
if (typeof x == "object") {
let pickedCard = Math.floor(Math.random() * x.length);
// This part does not match the overload definition.
return { suit: 'hearts', card: x % 13 };
} else if (typeof x == "number") {
let pickedSuit = Math.floor(x / 13);
return { suit: suits[pickedSuit], card: x % 13 };
}
}
const card = pickCard([{ suit: 'hearts', card: 5 }])
card.score.toFixed() // throw a runtime
实现与重载的定义不匹配,在这种情况下编译器不会警告我们,这意味着我们可能在运行时遇到问题,因为我们期望 number 但我们实际上得到了 string。是否期望编译器不会抛出?
你可以在the TypeScript playground里面测试样本。
【问题讨论】:
-
是的,这是意料之中的。你告诉编译器返回类型是
any。使用number | { suit: string; card: number; },它只允许返回它。您的x参数也是如此。并编写单元测试。 -
@JBNizet 是的,你是对的,但它解决了这个例子的问题,因为类型完全不兼容。想象一个不同的用例,两个类型的联合类型共享一些属性,我们又遇到了问题。
-
编译器不可能检查你在代码中可能犯的每一个错误。编写测试。进行代码审查。
-
是的,但这也是编译器的目的。
-
我用不兼容的类型更新了示例。
标签: typescript