Ended up going with `superstruct`. It's neat, a bit less verbose than io-ts and has better type inference in some places.
Native enums support is not there yet but can be worked around https://github.com/ianstormtaylor/superstruct/issues/993
The social network of the future: No ads, no corporate surveillance, ethical design, and decentralization! Own your data with Mastodon!