DEV Community

Cover image for Better Error Messages in TypeScript 4.2 - Smarter Type Alias Preservation
Omri Lavi
Omri Lavi

Posted on

Better Error Messages in TypeScript 4.2 - Smarter Type Alias Preservation

TypeScript 4.2 was recently released, 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.

Don't get lost when unioning types. (Photo by Emily Blincoe)

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, where the type of the parameter a is a union of two long types and undefined:

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)
Enter fullscreen mode Exit fullscreen mode

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.

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)
Enter fullscreen mode Exit fullscreen mode

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, these improvements were made possible by two pull requests, by Anders Hejlsberg (PR1 , PR2). 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!

Top comments (0)