Do you really know TypeScript? (4): Type assertions
Tags: javascript, webdev, typescript, programming
Published: 2022-01-06 18:25:55

In this post (the last of the series 😢) we are going to understand type assertions and compare them against type declarations.

## What do you use type assertions for?
There are situations where you know more than TypeScript can infer.

```typescript
let item: Item = {...}

type Item = {
  name: string
}

type FileItem =  Item & {
  extension: string
}

// We know for sure that item
// is also a file
printFile(item as File)

```
## Golden rule for using assertions
You can only assert from one type to another if either type is a subset of the other. 🧐

```typescript
type Car = {
  numOfDoors: number
}

type Airplane = {
  numOfEngines: number
}

const car: Car = {numOfDoors: 5}

// Conversion of type 'Car' to type 'Airplane' may be a mistake
// because neither type sufficiently overlaps with the other. 
const airplane = car as Airplane
```

An exception to this rule is when using `unknown` or `any`.
You can use these to bypass it:
- `unknown` because is the universal set
- `any` because disables the type checking

```typescript
const airplane = car as unknown as Airplane
```
## Prefer type declarations to type assertions
This is a mistake that I've seen a lot!

```typescript
type Car = {
  numOfDoors: number
  numOfAirbags: number
}

// Error: Property 'numOfAirbags' is missing
const car: Car = {numOfDoors: 5}

// No error
const car = {numOfDoors: 5} as Car
```

When you use type assertions you are telling TypeScript to get out of the way, with type declarations you are making your intentions clear so it can help you.

## Is `as const` a type assertion?
It is not. 
Despite having a similar syntax, `as const` is used to hint the type system about values being immutable.

It is very situational, but could be useful for using the values of an array as literals, for example:

```typescript
const coolBands = ['Oasis', 'AC/DC', 'Foo Fighters'] as const

// type CoolBands = "Oasis" | "AC/DC" | "Foo Fighters"
type CoolBands = typeof coolBands[number]
```

Or for using the values of an object:
```typescript
const coolBandsAndSingers = {
  'Oasis': 'Liam Gallagher',
  'AC/DC': 'Brian Johnson',
  'Foo Fighters': 'Dave Grohl'
} as const

// type CoolBands = "Oasis" | "AC/DC" | "Foo Fighters"
type CoolBands = keyof typeof coolBandsAndSingers

// type CoolSingers = "Liam Gallagher" | "Brian Johnson" | "Dave Grohl"
type CoolSingers = typeof coolBandsAndSingers[CoolBands]
```

As it is the last post of this series, I also want to go through some topics that couldn't get a post for their own. 

## Don't type everything!
I did it, and probably so did you. 

It is not bad, but can make the code too verbose and therefore harder to read.

As a rule of thumb, you should type very well:
- **Function and method signatures** (parameters and return types)
- **Variables and constants when using object literals**, to take advantage of excess property checking.

In a TDD like spirit, you should know your input and output types before implementing a function/method, so typing it from the beginning makes it easier for you to implement it.

Typing return types usually avoids implementation errors, specially if your function has many "paths".

## Don’t use uppercase variants of primitive types
Probably you noticed that `String` or `Number` exist and wonder if you should use them as types.

The answer is no. Just stick to lowercase types for primitives `string`, `number`, `boolean`, etc.

These uppercase variants exist primarily for convenience, for example:

```typescript
// charAt is not a property of
// the string primitive
"hey".charAt(1)

```
JavaScript wraps the `string` primitive in `String` under the hood and uses the `charAt` method of `String` and then throws that object away.

```typescript
// These wrappers don't have behave 
// as primitives

new String('hey') === new String('hey')

'hey' === new String('hey')
```


It's been a pleasure to write this series and I wish you a very productive experience with TypeScript 🙂

Thanks for reading!

## Resources to go deeper
- [Effective TypeScript](https://www.goodreads.com/en/book/show/48570456-effective-typescript)
- [TypeScript docs](https://www.typescriptlang.org/docs/)