Description
In JavaScript it’s common to see functions that can flatten and build up container types at arbitrary levels. Examples of these are:
- The
.then()
method on instances of promise..then(...)
unwraps each promise until it finds a value that’s not “fromise-like” and passes that value to a callback. - The Array flat & flatMap prototypes.
Since TypeScript 4.1, TypeScript eases some restrictions on conditional types, so that they can model those patterns. Conditional types can immediately reference themselves within their branches, making it easier to write recursive type aliases.
See the PR1 for the implementation.
Examples
Get the element types of nested arrays
Awaited type to deeply unwrap Promises
Caveats
Keep in mind that while these recursive types are powerful, but they should be used responsibly and sparingly.
First off, these types can do a lot of work which means that they can
increase type-checking time. Trying to model numbers in the Collatz
conjecture or Fibonacci sequence might be fun, but don’t ship that in
.d.ts
files on npm.
Apart from being computationally intensive, these types can hit an internal recursion depth limit on sufficiently-complex inputs. When that recursion limit is hit, that results in a compile-time error. In general, it’s better not to use these types at all than to write something that fails on more realistic examples.