我有一些代码:
enum Color {
Red,
Green,
Blue
}
function getColorName(c: Color): string {
switch(c) {
case Color.Red:
return 'red';
case Color.Green:
return 'green';
// Forgot about Blue
}
throw new Error('Did not expect to be here');
}
我忘记处理 Color.Blue
的情况,我宁愿得到一个编译错误。我如何构建我的代码,以便 TypeScript 将其标记为错误?
最佳答案
为此,我们将使用 never
类型(在 TypeScript 2.0 中引入),它表示“不应”出现的值。
第一步是写一个函数:
function assertUnreachable(x: never): never {
throw new Error("Didn't expect to get here");
}
然后在 default
情况下(或等效地,在 switch 之外)使用它:
function getColorName(c: Color): string {
switch(c) {
case Color.Red:
return 'red';
case Color.Green:
return 'green';
}
return assertUnreachable(c);
}
此时,您会看到一个错误:
return assertUnreachable(c);
~~~~~~~~~~~~~~~~~~~~~
Type "Color.Blue" is not assignable to type "never"
错误消息表明您忘记包含在详尽开关中的情况!如果您遗漏了多个值,您会看到有关例如Color.Blue |颜色.黄色
.
请注意,如果您正在使用 strictNullChecks
,则需要在 assertUnreachable
调用之前返回 return
(否则它是可选的) .
如果你愿意,你可以变得更漂亮一点。例如,如果您使用的是可辨别联合,则出于调试目的恢复断言函数中的可辨别属性可能很有用。它看起来像这样:
// Discriminated union using string literals
interface Dog {
species: "canine";
woof: string;
}
interface Cat {
species: "feline";
meow: string;
}
interface Fish {
species: "pisces";
meow: string;
}
type Pet = Dog | Cat | Fish;
// Externally-visible signature
function throwBadPet(p: never): never;
// Implementation signature
function throwBadPet(p: Pet) {
throw new Error('Unknown pet kind: ' + p.species);
}
function meetPet(p: Pet) {
switch(p.species) {
case "canine":
console.log("Who's a good boy? " + p.woof);
break;
case "feline":
console.log("Pretty kitty: " + p.meow);
break;
default:
// Argument of type 'Fish' not assignable to 'never'
throwBadPet(p);
}
}
这是一个很好的模式,因为您可以获得编译时安全性,以确保您处理了您期望处理的所有情况。如果你确实得到了一个真正超出范围的属性(例如,一些 JS 调用者组成了一个新的 species
),你可以抛出一个有用的错误消息。
关于typescript - 如何检查 TypeScript 中的开关 block 是否详尽无遗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39419170/