Type Folding and Options

Sometimes, I work with TypeScript compiler APIsThey’re great APIs!. Because the language semantics are non-trivial, traversing a TypeScript AST almost always involves extensive validation. Here’s a particularly specific traversal we use in the Angular Language ServiceIf the Language Service is something that interests you and would like to contribute, please let me know! Or nike swoosh it :slightly_smiling_face:.:

All validations branch on type checks, so in languages with design ideas like functors and monads we could find great solutions to simplifying the type folding done here. I want this to be a quick and (semi-)practical post, so I won’t explain what these words mean; instead, here’s an approach that I find simplifies this code.


First, Rust. Rust has an Option type that can be Something or Nonething. mapping an Option applies a predicate to a Some or propogates a None.

If the TypeScript API had Rust bindings, I would imagine the code above to look something like

My hot take is that is way nicer - declaring the procedure functionally and linearly makes it more readable to me.


Okay, so how do we get this in TypeScript? Well, for a variety of good reasonsMainly because TypeScript is focused on supplementing JavaScript with types, not with more language features that aren’t in the standard., OptionsTypeScript does provide an HTML Option, which is distinctly different. will probably never be in the standard library. Optional chaining will help, but won’t solve type mapping.

For domains where it is still useful to have Option (and other monad-family) types, there at least one library that can be used. If a library is too much, a lightweight Option can be written very quickly:

Will the Angular Language Service use Options? Probably not. But it’s a fun idea!