Every three months we get a new TypeScript release and TypeScript 5.1 landed on June 1, 2023. This release has a few interesting new features, but by far the most noticeable changes are performance improvements and error message ergonomics. Let's take a look!
When you hear "new TypeScript version", the natural tendency is to think about new language features. But what would you be more excited about: an exciting new feature like template literal types or a 10% faster compiler? Sorry, you can't have both!
The TypeScript team takes compiler performance incredibly seriously and every single set of release notes includes a few performance optimizations. A recent theme has been improving build times for projects that use complex libraries like Material-UI. The 5.1 release includes several optimizations that add up to a big win.
As readers of this blog may recall, Effective TypeScript is itself type-checked using literate-ts. The idea is that when new versions of TypeScript come out, I can quickly check whether any of the hundreds of code samples in the book produce new and unexpected errors. This is a great confidence booster that my book still matches reality, but it also means that Effective TypeScript can serve as a good gauge of what's changed between releases.
First let's look at performance:
- Checking Effective TypeScript (TS 5.0.4): 180.6s average
- Checking Effective TypeScript (TS 5.1.3): 170.9s average
That's about a 5% speedup. Not bad!
literate-ts is very sensitive to how error messages and types display. TypeScript 5.1 includes a nice change in how type errors on
return statements are displayed that didn't make it into the release notes. In previous versions of TypeScript, if you returned an expression of the wrong type, you'd get the dreaded red squiggles under both the
return keyword and the entire expression. For multiline expressions, this could be a lot of red!
With TypeScript 5.1, the red squiggles only appear under the
This is less distracting and makes it easier for you to inspect your code to find the source of the error. Not a huge change, but a nice win nonetheless. Next time you're debugging a type error in a
return statement, thank Mateusz Burzyński for the change!
Upgrading TypeScript often uncovers existing mistakes in your code and TS 5.1 was no exception. There was one new error that came up in a few of my projects.
TypeScript has long flagged duplicate keys in object literals:
But if you used computed keys, this error would go away:
With TS 5.1, this is an error:
This check only occurs for single-valued literal types.
The "headline" features in the official release notes for TS 5.1 are mostly niche changes that won't affect many users immediately. Here's a quick rundown:
- Easier Implicit Returns for undefined-Returning Functions I've never personally run across a function that was declared to return
void. But if you work with such functions, your life gets easier with TS 5.1.
- Unrelated Types for Getters and Setters This seems like a bad idea though as the CSS example in the release notes makes clear, this is an established pattern in the wild that TypeScript needs to model. I tend to avoid getters and setters (and classes in general). This relates to Effective TypeScript's Item 29: Be Liberal in What You Accept and Strict in What You Produce.
- Decoupled Type-Checking Between JSX Elements and JSX Tag Types This seems quite in the weeds, but the gist is that it's future-proofing for async React components, which may land sometime in the future. When these eventually land, we'll be happy that TypeScript supports them out of the box.
I was extremely excited about one other change in the TypeScript 5.1 RC that sadly got cut for the release: a "move to existing file" refactor. There's a nice video of this in action in the RC release notes. This has been a long-standing and much-upvoted feature request. You can move a symbol to a new file, but not to an existing file.
I have a workaround, but it's a bit gross. Say you want to move a symbol to an existing file
src/utils/my-utils.ts. Instead, move it to a new file
src/utils/new-file.ts. This will update all the imports for the symbol to point to the new file. Then cut/paste the definition of your symbol into
new-file.ts and run a big Find/Replace to update all the imports:
Like I said, gross! Hopefully this feature lands more permanently in TypeScript 5.2.
TypeScript 5.1 is not a major release when it comes to new language features, but it does include some performance wins, it may catch some new errors in your project, and it lays the groundwork for more changes in the future. Keep your eyes out for the TypeScript 5.2 beta which should be landing any day now and looks to have some exciting new features.