TypeScript 5.8 Checks Runtime Code for Conditional Types!

One of those “if you know, you know” releases.

Assumed audience: Advanced TypeScript developers who understand its conditional types feature.

The TypeScript 5.8 beta just dropped, and it has a huge feature in it. Right there at the top of the blog post: Checked Returns for Conditional and Indexed Access Types. From the perspective of a library author — particularly, a library author working on code which predates the library’s adoption of TypeScript — this solves one of the biggest pain points I have had historically.

Having conditional return types checked against the bodies of functions which use them is an absolutely massive win. Since their introduction, conditional types have been useful for writing standalone types for existing libraries (we did it a fair bit for Ember!), because a lot of JavaScript out there acts like this: the input determines the output, in statically-knowable but fairly dynamic ways.1 However, there was no connection to the runtime code that implemented that, so if you were working on the library code itself2 they were not only useless but actually required you to write more code that could be wrong.

The reason this is so useful with JS is because a lot of JS APIs were like this to start with: the types exposed the complexity that was already present. Most of the time, you actually want to avoid this kind of code when starting from scratch. But not always! There are a few spots in True Myth, for example, where we take advantage of this (or of similar techniques with overloads) to produce more useful types while still having fairly straightforward internal code.

The TS 5.8 beta announcement post covers this in some detail, including example code, so give it a read. I’m excited, even though the SemVer policy policy I use on True Myth (the only library I currently actively maintain) means it’ll be a while before we can use it. The day we can will be a good day, though!


Notes

  1. Now that runtime checking works, you can combine this with other corners of TypeScript to get some absolutely bonkers levels of type-driven programming. It is not remotely the same dependently-typed programming… but it might remind you of it. ↩︎

  2. Say: because you want to generate types from the library instead of authoring them by hand) ↩︎