Reputation: 7361
Take the following TypeScript code:
const a: 0 | 1 = 1
if (a === 0) {
console.log('a is 0')
}
The if
statement will generate the following error:
This condition will always return 'false' since the types '1' and '0' have no overlap.
(you can play around in in the TypeScript Playground with this example here: https://www.typescriptlang.org/play?#code/MYewdgzgLgBAhgLhgBhgHxgRhgXiwKHwEsAzGACjlxz2QEoYBvfGVmUSEAGwFMA6LiADm5AORUiEFKLr4AvkA)
My question is why does this throw an error? If you hover over the type of a
it is correctly typed as const a: 0 | 1
. If the compiler is so sure a
's type is always 1
, why doesn't it type it as const a: 1
?
NB: If you change the code to...
const a = 1 as 0 | 1
if (a === 0) {
console.log('a is 0')
}
...the error will go away. But it seems silly to revert to casting to fix this.
Upvotes: 1
Views: 783
Reputation: 25318
The "problem" here is that Typescript is smart enough to understand that const
can't be reassigned. This means that
const a: 0 | 1 = 1;
is the same for Typescript as doing
const a: 1 = 1;
Even though the type indicates there is a range of possible values, const
assignment limits the type to the only possible value.
You can see this in action when you hover a
in the conditional in the playground snippet you linked to: the type of a
in the if statement is 1
.
When you cast the type after the fact, you're manually overriding this constraint.
You can see the same operation in action when your variable declaration is let
but no assignment is made:
let a: 0 | 1 = 1;
// Same error as before, type of `a` is `1`
if (a === 0) {
console.log('a is 0');
}
If there's an assignment to the variable though, the type can't be constrained (because that would be the equivalent of the halting problem), and you'll have no error.
let a: 0 | 1 = 1;
if (some external condition) {
a = 0;
}
// No error, type of `a` is `0 | 1`
if (a === 0) {
console.log('a is 0')
}
Upvotes: 1