Javascript union类型的变量导致switch语句出错
假设我们有一个表示三个不同字符串值之一的联合类型Javascript union类型的变量导致switch语句出错,javascript,typescript,switch-statement,union-types,Javascript,Typescript,Switch Statement,Union Types,假设我们有一个表示三个不同字符串值之一的联合类型 type Animal = 'bird' | 'cat' | 'dog'; 现在,我想创造一只狗,并检查它是什么样的动物,以创造正确的噪音,它执行 let oscar: Animal = 'dog'; switch (oscar) { case 'bird': console.log('tweet'); break; case 'cat': console.log('meow'); break; c
type Animal = 'bird' | 'cat' | 'dog';
现在,我想创造一只狗,并检查它是什么样的动物,以创造正确的噪音,它执行
let oscar: Animal = 'dog';
switch (oscar) {
case 'bird':
console.log('tweet');
break;
case 'cat':
console.log('meow');
break;
case 'dog':
console.log('bark');
break;
}
此代码将导致TypeScript错误:类型“bird”与类型“dog”不可比较。ts(2678)
(与cat类似)。但是,如果我在变量oscar
上使用显式类型转换,则它可以正常工作:
switch (oscar as Animal) {
case 'bird':
...
case 'cat':
...
case 'dog':
...
}
如果我使用显式值表示oscar
,请解释为什么前两个switch语句失败
如果我将Oscar声明为常量,我可以理解这个错误:constoscar='dog'代码>,因为在这种情况下,它将始终是一只狗,而不是其他任何东西。然而,想象一下,如果一个巫师执行某个咒语,奥斯卡可能会变成一只猫:
let oscar: Animal = 'dog';
while(true) {
switch (oscar) {
case 'bird':
...
case 'cat':
...
case 'dog':
console.log('bark');
// here comes the wizard
if(wizard.performsSpell('makeOscarBecomeACat')) {
oscar = 'cat'; // that should be valid, because oscar is of type Animal
}
break;
}
}
我是否误解了变量oscar的赋值,或者这仅仅是一个TypeScript错误?您可能误解的是TypeScript 2.0及以上版本有一个名为的功能,在中实现。此功能的一个效果是
将S
类型的值赋值给T
类型的变量(包括声明中的初始值设定项),会在赋值后的代码路径中将该变量的类型更改为T
,并缩小S
。[…]由S
缩小的类型T
计算如下:[…]如果T
是联合类型,则结果是T
中的每个组成类型的联合,而S
是可分配的
这意味着声明
let oscar: Animal = 'dog';
解释为:“变量oscar
的类型为Animal
,是一种联合类型。它被分配了一个字符串文本类型“dog”
,因此在重新分配之前,我们将把变量oscar
视为Animal
缩小了“dog”
,即“dog”“
因此,在您的开关
/案例
语句中:
case 'bird': // error!
// ~~~~~~ <-- Type '"bird"' is not comparable to type '"dog"'
这可能都是好消息;编译器正在捕获永远不会发生的情况。在许多情况下,这些都是真正的bug
如果你不想让编译器意识到奥斯卡肯定是一只狗,只知道它是一只动物(比如说,在你编写真正可能成为动物的任何成员的代码之前,它是一个占位符),你可以在作业本身中使用:
let oscar: Animal = 'dog' as Animal;
现在,所有其他代码都将编译无误。您甚至可以忘记注释,因为它对您没有帮助:
let oscar = 'dog' as Animal;
好吧,希望这会有帮助;祝你好运
回答得很好,非常感谢您对窄联轴节类型的详细解释,这是一个我以前不知道但对我来说很有意义的概念。
let oscar = 'dog' as Animal;