Can anybody explain why the second variant doesn't work? Is it a bug?
const prints = (s: string): void => console.log(s);
var x: string | number = Date.now() % 2 ? "test" : 5;
// 1st: working
if (typeof x === "string") {
prints(x);
}
// 2nd: not working
var typex = typeof x === "string";
if (typex) {
prints(x);
}
The second variant shows the following error:
Argument of type 'string | number' is not assignable to parameter of type 'string'. Type 'number' is not assignable to type 'string'
TS Playground
TypeScript isn't intelligent enough to prove that x
in the second if
is indeed a string
. Since prints
only accepts a string
and it cannot prove that x
is a string
, it gives an error.
The first case, where the type check happens inside the if
conditional itself, works because TypeScript has a special case for understanding that kind of type check. However, the understanding that certain values in a certain variable could indicate the type of some other variable is more than it can handle. Yes, in this specific example, it looks like it should be trivial to figure it out, but it would very quickly become extremely difficult or even outright impossible for it to function in the general case.
If you absolutely want the second case to work, despite the type check being separate from the if
, you need to provide TypeScript with extra information by explicitly casting the value. For instance, using prints(x as string)
means "I guarantee that is is always a string
. If it's not, it's my fault when the program explodes." This type of cast is a signal to TypeScript that the developer knows something that it doesn't understand and blindly trusts it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With