1. 11
  1. 1

    Maybe I’m missing something obvious, but how is it different and why is it better than subtyping (extending a type)?

    e.g. type ConfirmedEmailAddress extends string

    1. 3

      In a nutshell, Elm’s opaque types give you a way to define types like ConfirmedEmailAddress without leaking their implementation details. This is impossible in TypeScript.

      I think I see where you’re going with your suggestion, but it won’t compile. The extends keyword is limited to interfaces and generics. Subtyping does exist in TypeScript, but it’s structural, i.e. in objects and interfaces. And even so, TypeScript will not distinguish between a ConfirmedEmailAddress object and an UnconfirmedEmailAddress object if their shape is the same. The author describes underscore-prefixed, pseudo-private properties as “branded types.” I hadn’t heard that term before, but underscores are all over the place in many languages and there’s always someone who ends up violating it out of some combination of desperation and expediency. Elm’s opaque types give you a guarantee that they are, to borrow a C# metaphor, sealed.

      In fairness, Elm and TypeScript were designed with different priorities in mind. TypeScript was designed to take the messy world of untyped JavaScript and incrementally add types to it. Duck typing is pretty consistent with that pragmatism. You can call it ConfirmedEmailAddress if you like, but if it walks like a string and talks like a string, TypeScript is going to treat it like a string.

      Elm, on the other hand, was designed to draw a sharp line with a functionally pure world (where the emphasis is on making impossible states impossible) on one side and the messy outside world (where anything goes) on the other.