Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

typescript typeof string doesn't work as expected

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

like image 752
AuthorProxy Avatar asked Jun 01 '21 10:06

AuthorProxy


1 Answers

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.

like image 67
BambooleanLogic Avatar answered Oct 12 '22 19:10

BambooleanLogic