TypeScript and ML languages

jkone27
5 min readFeb 6, 2022

--

Diverse approaches on typing the JavaScript ecosystem

Fable, the what, the why and the how (alfonsogarciacaro.github.io)

JS

function someFunction(a,b,c,d) {      return a + b + c + d; };

JavaScript is a dynamic language with weak type checking, which makes it wonderful to write little code and fast, but also quite awful for spotting bugs.

for this reason, among others, during the evolution of the language many attempts have been made to add additional typing or static type checking to the language.

The most successful attempt in this direction is without a doubt the TypeScript language by Microsoft.

Typescript basically allows JS developers to write java-like or C#-like JavaScript, with type annotations

Another known approach for static checking was done at Facebook with the Flow checker language extension.

We will quickly move to our example re-written in TS now…

TS

function someFunction(a: int, b: int, c:int, d:int): int {return a + b + c + d;};

Typescript allows you to enhance typing manually, or fall back to no types (any = js), the compiler works out the types in your code by manual type addition (annotation).

Typescript also allows developers to improve the domain modeling in their code base via tagged unions (a.k.a. Discriminated unions in other languages) but this feature was actually ported from ML languages, as well as pattern matching, and does look a bit wishy-washy to me.

TS tagged unions and TAG pattern matching

Let’s now take a look at how our function would look like in F# …

Fable

let someFunction a b c d = // all types inferred by the compilera + b + c + d

Fable is basically an F# to JS compiler (and more) which similarly to Reason ML or Elm, allows you to code in a ML language and have it compiled to JS in the end.

The good news is that F# is also a dotnet language (a server language), allowing you to write succinct, robust and performant code on the server as well as the client, re-using all the dotnet community packages and frameworks (e.g. Aspdotnet if you want to).

This is some short explanation of ML automatic type inference in F#…

ML type inference at work in F#

While Flow or TS requires developer type annotations (in a similar typescript fashion of typescript) to add most of the typing information for the compiler, and leaves just some spots filled in automatically, ML languages don’t require any typing information to be added by the developer, but you can always opt in with annotations to pin down specific types in your code if necessary.

ML Languages (Reason ML, F#, Elm)

F# logo

These 3 languages: OCaml (Reason), Elm and F# (Fable), share many of the same advantages with regards to automatic typing and dialect, allowing you to be explicit about types only when you want to do so.

As an extra point, once you learn one of these 3 languages, you should be able to easily read and understand most of them!

They all work somehow the opposite way of typescript, and they keep the succinctness of code closer to the original dynamic JS code, while helping with automatic typing in the background.

The compiler is usually better at giving the code the right type annotations, but types can also be pinned down in the signature when in need.

ReasonML function example

If you are familiar with Facebook Flow or ReasonML language, this should all make sense to you.

Elm logo

If you ever tried Elm, the same observations on typing holds alike, and the syntax is also quite close (just drop the let key):

myFunction a b c d = 
a + b + c + d

In addition to nice automatic typing, ML languages give the developer amazing support for real (not tagged types but actual types) discriminated unions and real pattern matching, useful for domain modeling.

F# example of real Discriminated Unions and real Pattern Matching

As a common origin, both Flow and Reason ML use some OCaml implementation behind the scenes to exactly take advantage of the Henry-Milner ML languages automatic type inference. And I presume similarly does helm with his own ML implementation.

By default, ML code is generic<T> and is constrained just with usage by the compiler.

Another amazing feature of ML languages is the ability to represent HTML as list comprehensions or just list structures containing other nodes

a view function in Elm

And similarly in F# Fable Feliz, in this case with underlying React.js support..

A Feliz React component using the Html module and functions

Give Fable (F# for JS) Elm, or Reason ML a try,

Have a nice weekend!

References

--

--