Why Elm Instead of TypeScript?
Or, yet another long comment in Slack turned into a blog post.
A few weeks ago, an acquaintance asked in a Slack channel weâre both in:
Can I ask a noob type Elm / JS question?
Why Elm instead of Typescript? The dev stack and functional programming?
I responded as follows, with only light tweaks to clarify a couple things (and Iâll be reusing some of this material as the basis of an internal tech talk Iâm giving on the same subject at Olo in a few weeks):
A couple things Elm gives you:
Itâs not tied to JS directly, which means itâs free to just do what is the best fit for the language rather than needing to be able to express all the quirks and oddities of JS. Thatâs the single biggest thing I find all the time with TS (which I use every day and do quite like): as good as it is, and as both powerful and expressive as its type system is, at the end of the day itâs⦠still a superset of JavaScript, and that can mean some really nice things, but it also means a lot of weird things.
Elmâs type system is sound; TypeScriptâs is not. At a practical level, that means that if an Elm program type-checks (and thus compiles), you can be sure â not mostly sure, 100% sure â that it is free of things like
undefined is not a function
. TypeScript does not (and by design cannot) give you that guarantee. And when I say âby design,â I mean that its designers believed from the outset that soundness was in tension with developer productivity, so they intentionally left a number of âsoundness holesâ in the type systemâthereâs still a lot of opportunity forundefined is not a function
, sad to say. You can make it less than in JS⦠but not none. (Thatâs even still true in the TypeScript 2.x series, though the various soundness flags they added in 2.0 and the--strict
option coming in 2.3 do get you closer.) In Elm, you can make it truly none. Itâs just a sort of known fact at this point that Elm codebases tend to have zero runtime errors.Elmâs language design is a huge win.
Elm is a pure functional language. Because non-pure things are offloaded to the Elm runtime, every single function you write is pure. Same input means the same output.
Elm supports first-class currying and partial application. This makes it much, much easier to do the kind of functional-building-block approach that is natural in FP and which is attractive in (but a lot more work in) JS or TS. Example code to show what I meanâ
Javascript:
const add = (a, b) => a + b; const add2 = (c) => add(2, c); const five = add2(3);
Elm:
add a b = a + b add2 = add 2 five = add2 3
The combination of the above means that you can refactor and always be sure you get everything, which is truly magical. And the compiler errors are the best in the world (and thatâs no exaggeration).
The way Iâd summarize it is to say that Elm makes it easy to do the right thing and hard or impossible to do the wrong thing. TypeScript makes it possible to do the right thing, and gives you a couple switches you can flip to make it harder to do the wrong things, but will ultimately let you do anything.