Average Joe
Average Joe

Reputation: 4601

Typescript type conversion

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?

Upvotes: 4

Views: 3333

Answers (1)

jcalz
jcalz

Reputation: 328302

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!

Upvotes: 8

Related Questions