Type Assertions, Trucks, and Aliens
Tags: typescript, javascript, webdev, beginners
Published: 2022-12-04 14:46:23

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](https://www.typescriptlang.org/docs/handbook/intro.html). As I am reading the part about [type assertions](https://www.typescriptlang.org/docs/handbook/intro.html) (the `as` keyword); I couldn't help but think back to a [StackOverflow answer](https://stackoverflow.com/questions/71190622/multiple-type-assertions-in-typescript/71190990#71190990) 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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/373ksydywucq1g4d450p.jpg)

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](https://en.wikipedia.org/wiki/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](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#type-assertions) 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:
> ```typescript
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:
```typescript
const myVar = 42 as string; // Error, sending nuclear launch codes to Russia!
```
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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/91r1qp6gysehtfryq3qg.jpg)

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???
```typescript
const myVar = 42 as any as string;
```
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:
```typescript
interface Truck {
  color: string;
  numDoors: number;
  drive: () => void; // truck method to drive, cause all trucks drive
}
```
the other is a plane:
```typescript
interface Plane {
  color: string;
  numPropellers: number;
  fly: () => void; // plane method to fly, cause all planes fly
}
```
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:
```typescript
const truck: Truck = <insert truck object> as Plane
``` 
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?
```typescript
const truck: Truck = <insert truck object> as any
```
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! 
```typescript
const truck: Truck = <insert truck object> as any as Plane
```
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:
```typescript
const myVar = 42 as any as string;
```

## 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:
```typescript
interface FlyingTruck extends Truck {
  // You will get all the properties of the Truck type
  fly: () => void // Plus the ability to fly!
}
```
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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0khvw7t56ouyfmfphm9o.gif)