Is it true that TypeScript allows us to override its inferred and analyzed view of types in any way we want to?
Consider the following simple example please
let myAge: number;
myAge = window.prompt('age?');
// we cannot do this because window.prompt returns a string
// so we need a type assertion, but the 2 ways I know does not cut it
let myAgeStr: string;
myAgeStr = window.prompt('age?');
// method 1
myAge = myAgeStr as number; // fails
// method 2
myAge = <number> myAgeStr; // also fails
Fails means Type 'string' is not assignable to type 'number'.
What do we do then?
TL;DR you can do it but you probably don't want to. Parse the string as a number.
Type assertions from one type to another are only allowed when at least one of the types is assignable to the other. There's the safe "up casting" direction, where a you widen a value to a supertype (throwing away information):
// safe
let h = "hello" as (string | number); // widening string to string|number
And there's the unsafe "down casting" direction, where you narrow a value to a subtype (adding information the compiler can't verify):
// unsafe but correct
let okay = h as "hello"; // narrowed string|number to string literal "hello"
// unsafe and incorrect
let notOkay = h as "goodbye"; // narrowed string|number to string literal "goodbye".
But what you can't do is do type assertions between two unrelated types, where neither one is assignable to the other:
let s = "string";
s as number; // error
let n = 1;
n as string; // error
Enter any, the escape hatch from the type system. The type any is considered assignable to and from every other type. If you really want to assert a value is an unrelated type, you can use any as an intermediary. This is quite unsafe, of course:
n = s as any as number; // you're the boss
s = n as any as string; // you're the boss
So you can do it:
myAge = window.prompt('age?') as any as number; // bad idea
But please don't do it. TypeScript is warning you, correctly, that a string is not a number. Sure, lots of JavaScript functions will coerce a string to a number if that's what they expect, but lots of JavaScript functions won't do that:
n = "3" as any as number;
console.log(n + 5); // 35, not 8!
So it's really a bad idea to force TypeScript to allow you to do foolish things. If you want to interpret a string as a number, parse it:
let myAge: number;
myAge = Number(window.prompt('age?')); // always a number, may be NaN
The Number function will always return a number, and TypeScript knows this, and now both you and TypeScript are happy, both at compile time and runtime. Do keep in mind that NaN is a number and that's what you'll get if you do something like Number("hello"). So after getting myAge as a number, you probably want to check it via isNaN() before doing anything numeric with it.
Hope that helps; good luck!
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