DEV Community

Cover image for Type Assertions, Trucks, and Aliens
about14sheep
about14sheep

Posted on

Type Assertions, Trucks, and Aliens

Buckle up, yo.

I'm listening to R&B right now

It's extremely early where I am, and I couldn't sleep. So like any logical person would be doing, I was reading through the TypeScript Handbook. As I am reading the part about type assertions (the as keyword); I couldn't help but think back to a StackOverflow answer I wrote about multiple type assertions. Don't get me wrong, I like my answer. However, it's just that its... well its...

Even more boring than this dude

While laying there I had an epiphany, the likes of which would make every Ancient Astronaut Theorist proud. I could spice up the explanation of type assertions (and make it more understandable) if I added aliens.

What even is TypeScript?

If you don't know what TypeScript is, you should. That's all I have to say about that.

Type Assertions

Now that it's just the TS nerds; lets talk about Type Assertions. In short (because obviously I am going to explain it WAY cooler further down), a type assertion is you telling the compiler whats up. The compiler isn't the great Giorgio A. Tsoukalos, sometimes you just know better. Type Assertions allow you to tell the compiler that a particular type will behave like another (i.e. have the same shape). I won't bog us down with code yet, and the handbook has a great example so i'll just steal that:

For example, if you’re using document.getElementById, TypeScript only knows that this will return some kind of HTMLElement, but you might know that your page will always have an HTMLCanvasElement with a given ID.

In this situation, you can use a type assertion to specify a more specific type:

const myCanvas = document.getElementById("main_canvas") as HTMLCanvasElement;

That's all well and good, pretty easy to understand. However, there are obvious limitations to this. What if I tried to tell the stoopid computer machine this:

const myVar = 42 as string; // Error, sending nuclear launch codes to Russia!
Enter fullscreen mode Exit fullscreen mode

TypeScript will throw a fit, and its correct to do so. The compiler is smart enough to know there is no possible way this number 42 can behave like a string. Instead of me grinding this down, you go try it in plain old JavaScript. Try and read the .length property of 42 and see if you don't cause World War 3.

¿¿¿Where Aliens???

where banana but its aliens

If the compiler is so smart, why does asserting 42 to the type any (or unknown) allow me to then assert it as a string??? Am I bamboozling the compiler???

const myVar = 42 as any as string;
Enter fullscreen mode Exit fullscreen mode

Can I now magically call the .length property of 42 and not cause World War 3?

Slow down on the questions, it's early and the coffee is still brewing.

The answer to 42.length is still no. That will NEVER be a thing. Give it up already, kid.

However, you are bamboozling the compiler. When you cast the multiple type assertion spell, it makes the compiler immediately believe you (there is not even a saving roll). It throws its little compiler hands up and says "ok dungeon master, you know best" and goes about its day.

Why you ask, again? That's where the aliens come in.

No more memes, just facts

Now that it's really just the TS nerds; let's start with two data types, one is a truck:

interface Truck {
  color: string;
  numDoors: number;
  drive: () => void; // truck method to drive, cause all trucks drive
}
Enter fullscreen mode Exit fullscreen mode

the other is a plane:

interface Plane {
  color: string;
  numPropellers: number;
  fly: () => void; // plane method to fly, cause all planes fly
}
Enter fullscreen mode Exit fullscreen mode

Lets just focus on the truck for now. If I were to show you this truck (const truck: Truck) you would be able to assume it does truck things. You would expect a number of doors to access it, its color, and other truck things. If I told you to go and drive the truck (truck.drive()) you would see no problem thinking you could hop in and drive it.

What if I told you to fly (truck.fly()) the truck? You would throw a syntax error and remind me that it is physically impossible for trucks to fly; that's what planes do.

Even if I said, think of this truck as a plane:

const truck: Truck = <insert truck object> as Plane
Enter fullscreen mode Exit fullscreen mode

You would probably slap me and leave the room. You can not be fooled so easily, you are a smart compiler!

Now what if I told you it was an alien truck?

const truck: Truck = <insert truck object> as any
Enter fullscreen mode Exit fullscreen mode

Well now it could be anything (the any type you might say?). You have no idea what them aliens be doing these days. It is perfectly plausible that an alien truck can fly!

const truck: Truck = <insert truck object> as any as Plane
Enter fullscreen mode Exit fullscreen mode

You would have no problem getting in the truck and attempting to make it fly. You do so truck.fly(), and the truck explodes.

That's what multiple Type Assertions are doing (and the dangers!). By broadening the type to any anything is possible. So its then perfectly valid (syntactically) to narrow an any type down to a string in our example:

const myVar = 42 as any as string;
Enter fullscreen mode Exit fullscreen mode

BUT WHAT ABOUT 42.length??

You would be correct in worrying about this. Since the compiler does not care, you could run this code. In code the "alien" veil will come off revealing a regular old truck trying to fly, when it can't. Then the program crashes just as the truck would.

However, there is a correct way to do this. Instead of going to aliens for a flying truck, you could just invent it like the genius you are!

In TypeScript you can extend interfaces to add functionality to them, so to make your special truck you would simply:

interface FlyingTruck extends Truck {
  // You will get all the properties of the Truck type
  fly: () => void // Plus the ability to fly!
}
Enter fullscreen mode Exit fullscreen mode

And Presto! You have now invented the flying truck. When you then instantiate a FlyingTruck object you will be able to fly that bad boy without any issue. The compiler is happy, the JavaScript interpreter is happy, Giorgio A. Tsoukalos is happy, and you know what? I'm happy.

Felt clever, might delete later

If you liked this article (or just love TypeScript as much as I do) let's talk about it! In the comments, though, to drive engagement on the post ;)

lol this one moves

Top comments (2)

Collapse
 
darkflames profile image
DarK FlameS • Edited
const myVar = 42; 
const myVarToString = ""+myVar;

myVarToString.length
Enter fullscreen mode Exit fullscreen mode

Ugly, but works ¯\(ツ)

Collapse
 
about14sheep profile image
about14sheep • Edited

lol nice