Hacker News new | ask | show | jobs
by kaoD 758 days ago
> 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...

1 comments

This is a far better summary of branded types than the top level comment that most people commenting should read before weighing in with their "why not just" solutions.