admin管理员组文章数量:1312811
Consider we have a union type that represents one of three different string values.
type Animal = 'bird' | 'cat' | 'dog';
Now I would like to create a dog and check what kind of animal it is to create the correct noise it performs.
let oscar: Animal = 'dog';
switch (oscar) {
case 'bird':
console.log('tweet');
break;
case 'cat':
console.log('meow');
break;
case 'dog':
console.log('bark');
break;
}
This code will result in a TypeScript error: Type '"bird"' is not parable to type '"dog"'.ts(2678)
(analog with cat). However, if I use an explicit type cast on the variable oscar
, it works without problems:
switch (oscar as Animal) {
case 'bird':
...
case 'cat':
...
case 'dog':
...
}
Can you please explain to me why the first two switch statements fail if I use an explicit value for oscar
?
I could understand the error if I declared Oscar as a constant: const oscar = 'dog';
, because in that case it would always be a dog and nothing else. However, just imagine for a moment that Oscar could bee a cat if a wizard would perform a certain spell:
let oscar: Animal = 'dog';
while(true) {
switch (oscar) {
case 'bird':
...
case 'cat':
...
case 'dog':
console.log('bark');
// here es the wizard
if(wizard.performsSpell('makeOscarBeeACat')) {
oscar = 'cat'; // that should be valid, because oscar is of type Animal
}
break;
}
}
Do I misunderstand something about the assignment of the variable oscar
, or is this simply a TypeScript bug?
Consider we have a union type that represents one of three different string values.
type Animal = 'bird' | 'cat' | 'dog';
Now I would like to create a dog and check what kind of animal it is to create the correct noise it performs.
let oscar: Animal = 'dog';
switch (oscar) {
case 'bird':
console.log('tweet');
break;
case 'cat':
console.log('meow');
break;
case 'dog':
console.log('bark');
break;
}
This code will result in a TypeScript error: Type '"bird"' is not parable to type '"dog"'.ts(2678)
(analog with cat). However, if I use an explicit type cast on the variable oscar
, it works without problems:
switch (oscar as Animal) {
case 'bird':
...
case 'cat':
...
case 'dog':
...
}
Can you please explain to me why the first two switch statements fail if I use an explicit value for oscar
?
I could understand the error if I declared Oscar as a constant: const oscar = 'dog';
, because in that case it would always be a dog and nothing else. However, just imagine for a moment that Oscar could bee a cat if a wizard would perform a certain spell:
let oscar: Animal = 'dog';
while(true) {
switch (oscar) {
case 'bird':
...
case 'cat':
...
case 'dog':
console.log('bark');
// here es the wizard
if(wizard.performsSpell('makeOscarBeeACat')) {
oscar = 'cat'; // that should be valid, because oscar is of type Animal
}
break;
}
}
Do I misunderstand something about the assignment of the variable oscar
, or is this simply a TypeScript bug?
1 Answer
Reset to default 8What you might be misunderstanding is that TypeScript 2.0 and above has a feature called control-flow based type analysis, implemented in microsoft/TypeScript#8010. One of the effects of this feature is that
An assignment (including an initializer in a declaration) of a value of type
S
to a variable of typeT
changes the type of that variable toT
narrowed byS
in the code path that follows the assignment. [...] The typeT
narrowed byS
is puted as follows: [...] IfT
is a union type, the result is the union of each constituent type inT
to whichS
is assignable.
That means the statement
let oscar: Animal = 'dog';
is interpreted as: "the variable oscar
has the type Animal
, a union type. It has been assigned a value of the string literal type "dog"
, so until it gets reassigned, we will treat the variable oscar
as the type Animal
narrowed by "dog"
, which is just "dog"
.
And therefore in your switch
/case
statement:
case 'bird': // error!
// ~~~~~~ <-- Type '"bird"' is not parable to type '"dog"'
You get the error about trying to pare a string literal "bird"
to a string literal "dog"
. The piler knows that the 'bird'
case is impossible because you have not reassigned oscar
to something patible with 'bird'
.
Even in your wizard
case, the piler understands that when it reaches the switch
/case
statement, oscar
can only be "cat"
or "dog"
and not "bird"
:
case 'bird': // error!
// ~~~~~~ <-- Type '"bird"' is not parable to type '"cat" | "dog"'
This is all probably good news; the piler is catching cases that can never happen. For many situations these are genuine bugs.
If you want the piler not to realize that oscar
is definitely "dog"
and only know that it's an Animal
(as, say, a placeholder until you write code that makes it genuinely possible for it to be any member of Animal
), you can use a type assertion in the assignment itself:
let oscar: Animal = 'dog' as Animal;
Now all your other code will pile without error. You can even forget the annotation since it wasn't helping you:
let oscar = 'dog' as Animal;
Okay, hope that helps; good luck!
Playground link to code
本文标签: javascriptVariable of union type causes error in switch statementStack Overflow
版权声明:本文标题:javascript - Variable of union type causes error in switch statement - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741879644a2402668.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论