Better Error Messages in TypeScript 4.2 - Smarter Type Alias Preservation
Tags: typescript, javascript, webdev
Published: 2021-02-28 19:05:18

TypeScript 4.2 was [recently released](https://devblogs.microsoft.com/typescript/announcing-typescript-4-2/), with many cool new features and improvements. It's really impressive to see how TypeScript improves the developer experience one step at a time. 
In this short post we will focus one feature, called Smarter Type Alias Preservation. I can say for myself that I really anticipate this feature. In a nutshell, it improves error messages related to union-types of union-types. I hope that in a few minutes you'll understand better what it means, and why it is useful.

![Don't get lost when unioning types.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b7vhmm0echeyydsa3lov.png)

<sup>Don't get lost when unioning types. (Photo by [Emily Blincoe](https://www.thisiscolossal.com/2015/06/painstaking-new-arrangements-of-colorful-objects-and-food-by-emily-blincoe/))</sup>

## So What's the Problem?

Until TypeScript 4.2, when using a union type which contained at least one union type, the compiler "flattened" the types. In simpler terms - you couldn't tell which types the union-type holds. Consider the following simplified [example](https://www.typescriptlang.org/play?ts=4.1.5#code/C4TwDgpgBAMg9gOwOYBVwQIxQLwFgBQA5KJBoVAD4HHoBM5VRJEAzA9cwCztPoCsPGpABsg5gHYx6ABxTIATjmYADEoxlKHdBnqbepNnqGZuR5hgFntoq6Um3MshxkUBuAh-zNYiVHRzUAPrmgsF0ocyGjIRhkKbRsRCWCcw2Kej26ZBOWRCKRokYqgXmGrk6EdpRQebxNdrJ9aRpTZiZrRg5HW6eBABmAK4IAMbAAJaIUAC2IABiQ8NQABQAhgBcPshopJSbfpC0u0MAJhB9YwgQxwCUUADeBFBQAE4QwAPPCFAr7vgAvr18DN5iMloQAEYDKZTCDPQjXVxQAD0SKgAEFnkgoRAEMAoHA+lBvIQAESQ6GwknkMYAZygCDgeJWNJpYyQCBW4IANtBgHAoGAVs8VjDgLD8YTiSTzCTdtK6LKKFB5ZAWIrlVx1SqkuqAHT6qAsFjTOCvKD63VHBCnc6XY6EXVLWgsTh8a5AA), where the type of the parameter `a` is a union of two long types and `undefined`:

```tsx
type LongType1 =
'type1' |
'type2' |
//...
'type19';

type LongType2 =
'_type1' |
//...
'_type19';

function myFunc (a: LongType1 | LongType2 | undefined) {
  return a;
}

myFunc('bummer'); // Argument of type '"bummer"' is not assignable to parameter of type '"type1" | "type2" | "type3" | "type4" | "type5" | ... 33 more ... | undefined'.(2345)
```

It's very difficult to understand this error: Where are these string literals coming from? Which type should I be looking at? What's the rest of the `33 more` valid values? This can cause a lot of confusion and frustration.

## What's New?

TypeScript 4.2 is going to make your lives easier in this aspect. **Smarter Type Alias Preservation makes TypeScript "remember" which union-types are being used while displaying the error messages**. Instead of flattening the union-types, their alias will be preserved and shown. See the [same code from the previous example, compiled with TypeScript 4.2](https://www.typescriptlang.org/play?ts=4.2.0-beta#code/C4TwDgpgBAMg9gOwOYBVwQIxQLwFgBQA5KJBoVAD4HHoBM5VRJEAzA9cwCztPoCsPGpABsg5gHYx6ABxTIATjmYADEoxlKHdBnqbepNnqGZuR5hgFntoq6Um3MshxkUBuAh-zNYiVHRzUAPrmgsF0ocyGjIRhkKbRsRCWCcw2Kej26ZBOWRCKRokYqgXmGrk6EdpRQebxNdrJ9aRpTZiZrRg5HW6eBABmAK4IAMbAAJaIUAC2IABiQ8NQABQAhgBcPshopJSbfpC0u0MAJhB9YwgQxwCUUADeBFBQAE4QwAPPCFAr7vgAvr18DN5iMloQAEYDKZTCDPQjXVxAA).

```tsx
type LongType1 =
'type1' |
'type2' |
//...
'type19';

type LongType2 =
'_type1' |
//...
'_type19';

function myFunc (a: LongType1 | LongType2 | undefined) {
  return a;
}

myFunc('bummer'); //Argument of type '"bummer"' is not assignable to parameter of type 'LongType1 | LongType2 | undefined'.(2345)
```

As you can see, TypeScript "remembers" that `"type1" | "type2" | ... | "type19"` is actually `LongType1`, and that `"_type1" | "_type2" | ... | "_type19"` is `LongType2`. TypeScript indeed got smarter with type alias preservation! The error is much more intuitive, so now you can shift your frustration towards something else. 

As [Daniel Rosenwasser mentioned in the announcement](https://devblogs.microsoft.com/typescript/announcing-typescript-4-2/#smarter-type-alias-preservation), these improvements were made possible by two pull requests, by Anders Hejlsberg ([PR1](https://github.com/microsoft/TypeScript/pull/42149) , [PR2](https://github.com/microsoft/TypeScript/pull/42284)). I will not get into the implementation details here. However, I encourage you to skim through the changes in `src/compiler/checker.ts`, or the pull requests' descriptions.

# Wrap Up

TypeScript 4.2 will bring many exciting new features. One of which is the Smarter Type Alias Preservation, which will make certain type-errors much more informative. I hope that now you have a better grasp of this feature's meaning. Union-types have never been better!