| > I also don't really get what this branded type adds beyond the typical way of doing it Your example is a (non-working) tagged union, not a branded type. Not sure about op's specific code, but good branded types [0]: 1. Unlike your example, they actually work (playground [1]): type Hash = string & { tag: "hash" }
const doSomething = (hash: Hash) => true
doSomething('someHash') // how can I even build the type !?!?
2. Cannot be built except by using that branded type -- they're actually nominal, unlike your example where I can literally just add a `{ tag: 'hash' }` prop (or even worse, have it in a existing type and pass it by mistake)3. Can have multiple brands without risk of overlap (this is also why your "wrap the type" comment missed the point, branded types are not meant to simulate inheritance) 4. Are compile-time only (your `tag` is also there at runtime) 5. Can be composed, like this: type Url = Tagged<string, 'URL'>;
type SpecialCacheKey = Tagged<Url, 'SpecialCacheKey'>;
See my other comment for more on what a complete branded type offers https://news.ycombinator.com/item?id=40368052[0] https://github.com/sindresorhus/type-fest/blob/main/source/o... [1] https://www.typescriptlang.org/play/?#code/C4TwDgpgBAEghgZwB... |