Note on typed and functional JavaScript

Dynamic type system

Dynamic type system: ES6 almost LISP (Scheme)

Given the fact that ES6 has dynamic type system, higher order functions (e.g. functions which can accept and/or return other function), tail call optimisation (TCO), brings ES6 to level of LISP (Scheme).

First time this idea was suggested by Douglas Crockford. But Crockford suggested it when there was no TCO in standard.

With TCO and fat arrow (=>) ES6 become closer to LISP (in some aspects) e.g. you can take SICP and implement all examples using ES6. Yay!

Side note: there exist variations of LISP with static type system, but historically LISP was dynamically typed.

Dynamic type system plus immutable data structures: Clojure

First of all there is ClojureScript which will transpile Clojure (with some restrictions) to JS.

Or you can use ES6 together with immutable (functional) data structure, for example mori (which come from ClojureScript) or Immutable.js.

Side note: using ES6 with immutable data structures is not the same thing as using ClojureScript, it is some kind of equivalent.

Static type system: JavaScript with types

There are two big players in this field: Flow and TypeScript. Both of those systems not “sound” for the same reason: structural subtyping. Take a look this video with creators of both systems: Typed JavaScript with TypeScript and Flow.

I believe one of the sell points for those systems is ease of integration with existing JS ecosystem. To be able to do this you need to add type description to existing code. There are community-driven repositories of description files. It would be cool if there would be some kind of interportability between formats, so they can be shared. As of now type systems are bit different.

Flow

Flow is a static type checker for JavaScript by Facebook.

Sound: no.

Flow supports this idiom. As far as we know, this is a type system novelty: supporting this idiom while balancing other constraints of the type system, such as sound subtyping over objects and prototypes, can be quite tricky! Flow Object

Simple FFI e.g. description (header) files: Yes. Repository: flow-typed

There is no standard higher kind library, but there is flow-static-land, which looks promising.

TypeScript

TypeScript is JavaScript superset with types by Microsoft.

Sound: no. See: type compatibility

Simple FFI e.g. description (header) files: Yes. Repository: DefinitelyTyped

Static type system: Raise of ML languages

There is interesting tendency: raise of ML-family (closer to OCaml) languages which can be transpiled to JS. One of the most intriguing is BuckleScript, which is able to transpile OCaml.

OCaml - mature functional language with safe type system.

  • BuckleScript is a backend for OCaml which emits readable, modular and highly performant JavaScript. Human-readable output.
  • Reason is a new interface to OCaml - a highly expressive dialect of the ML language featuring type inference and static type checking. It has more familiar appearance for JavaScript programmers.

F#

Fable optimizes F# code to generate as clean JavaScript as possible. It comes with a tiny core library (around 20KB minified and gzipped) and no other runtime.

On the other side there are also new languages. Which fails in ML-family too (OCaml/Haskell).

Elm Generate JavaScript with great performance and no runtime exceptions. Comparison to ML and Haskell. Pros: explicitly handles effects, immutable, fantastic error messages. Cons: need to write special code to wrap existing JS libraries (I would call it complex FFI).

PureScript is a small strongly typed programming language that compiles to JavaScript. Features: human-readable output, extensible effects, algebraic data types, higher kinded types, simple FFI (at least that’s what it is promising) and many more.

Other

There is also Dart, of which I do not know much. Does anybody else than Google use it?

  Type System Immutability Sound ADT Effects Simple FFI FFI Definitions/Packages Human readable output Server
ES6 Dynamic No - - - - - ? Yes
ClojureScript Dynamic Yes - - - ? ? ? Yes
Flow Static No No Yes ? Yes 117 flow-typed, flowInterfaces ? Yes
TypeScript Static No No Yes ? Yes 2,073 DefinitelyTyped ? Yes
OCaml (BuckleScript) Static ? No Yes Yes ? Yes ~4 + ? bindings Yes Yes
F# (Fable) Static No ? Yes Yes ? ? ? ? ?
Elm Static Yes ? Yes Yes Yes No ? package ? ? No
PureScript Static ? Yes ? Yes Yes Yes Yes 212 pursuit Yes ?
  • Immutability - if immutability is the feature of language
  • Sound - type soundness
  • ADT - Algebraic data types
  • Effects - if type system takes into account side effects
  • Simple FFI - it is enough to describe function signatures to use third-party JavaScript code. No need for additional boilerplate code
  • FFI Definitions/Packages - number of third-party packages in repository
  • Human readable output - if output of transpiler is JavaScript module which you can easily use in JavaScript, if variables mangled
  • Server - if it is possible to use on server-side