Staticly Typed JavaScript Language and Library Options

Over the last 3-6 years, staticly typed languages and libraries like TypeScript, Flow, and Dart have steadily gained traction in the world of JavaScript web development. More developers, teams, and companies are adopting them every week.

This article will explore why these technologies exist and explore some of the nuances and characteristics of the major ones.

Strong, weak, static and dynamic

One of the first challenges with understanding typing as it relates to web development is understanding the difference between strong, weak, static, and dynamic typing. Strong and static (and weak/dynamic respectively) sometimes get used synonymously. This is incorrect. Yes, JavaScript and PHP are dynamically and weakly typed. But a language like Python is dynamically AND strongly typed. Avoid the tendency to think strong = static. Several great StackOverflow answers clarify the differences between these four terms. I’ll summarize the gist of these:

Static typing means that programs are checked before being executed, and a program might be rejected before it starts. Here’s an example in Java:

Dynamic typing means that you change a variable’s type. You can change the variable’s type of string, for example, to a boolean or integer. The language will let you do that. That is because typing is associated with the value rather than the variable. Here’s an example in Python:

Strong and weak typing, on the other hand, generally refer to something called implicit type conversions. As you were learning JavaScript, you probably remember wacky operations that combine Booleans with integers and strings with nulls like these:

source: https://javascript.info/task/primitive-conversions-questions

Each of the above are examples of weak typing. JavaScript allows for a very forgiving combination and conversion of different types of variables. This is awesome for flexibility but can cause all sorts of bugs and confusion in the code. Python, on the other hand, is strongly typed, so these implicit type conversions won’t fly.

Source: https://stackoverflow.com/a/2351869

Statically typed languages are usually compiled, and dynamically typed languages are usually interpreted. Here are the top 10 TIOBE index languages on a 2×2 matrix of these 4 types of typing:

As you see, some sit the middle as developers point out that they can have a bit of both strong and weak typing (or it can be decided by the developer).

The advantages and disadvantages of weak and dynamic typing

Dynamic typing, free of type annotations, allows for faster prototyping and less verbose code. This is where JavaScript and PHP shine. Eric Elliot lays out the potential disadvantages of static typing quite succinctly:

Type annotations [in static typing] obviously create[s] more syntax noise, and that syntax makes code harder to read, and harder to maintain. But the drawbacks go a little deeper. Specifically, static types can make all of these things harder (not impossible, just more complicated than they need to be):

  • Generic functions & polymorphism
  • Higher order functions
  • Object composition

That’s a drag, because I use all of those things a lot, and if you’re a fluent JavaScript coder, chances are good that you use them a lot, too.

But in exchange for this verbosity, static typing offers many advantages. The biggest advantage is that a whole category of bugs gets detected earlier in the development cycle. These bugs come from the simple mistake of passing the wrong type of variable (e.g. integer instead of string) to the wrong function, loop or class. Because these bugs get detected earlier, it makes it easier to refactor and collaborate on code. In a recently published paper called To Type or Not to Type: Quantifying Detectable Bugs in JavaScript (pdf here), researchers found that 15% of the bugs that end up in committed code could be solved by using static typing. The caveat with that piece is that one of the main authors works for Microsoft (creators of TypeScript). This is not to say the piece is biased, only that the conclusion supports his company’s sponsored language. And so it goes. This is a great place to switch to talking about TypeScript, the most popular static language for front-end development.

TypeScript

TypeScript was launched by Microsoft for public use in October 2012. TypeScript is a superset of JavaScript, making all JavaScript valid TypeScript code. If you’re unfamiliar with supersets, know that Objective-C is a superset of C and Java 7 is a superset of Java 8. TypeScript needs to be compiled to JavaScript (so the browser can read it) using a compiler that is actually written in TypeScript.

A search of Indeed’s job listings shows that 3000+ jobs use the term ‘TypeScript’ (compared to 43000+ that use JavaScript). Google trends shows TypeScript gaining search volume every year since its release.

The core feature of TypeScript is arguably its optional static typing. Here’s an example of how a simple JavaScript function is written with TypeScript static typing:

Source

You’ll also notice how variable declarations also use the ‘:type’ syntax:

In exchange for the verbosity, we get clear static typing in the examples above. The program won’t compile if the developer slips up and uses the wrong type. These upfront errors save a lot of bugs down the line.

Static typing isn’t the only benefit of TypeScript. Developers also report that it offers a better IDE experience and generally more readable and self-documenting code. Many developers use TypeScript for building React.js applications while others prefer to use Facebook’s flow.

Flow

Flow is a static type checker, designed to quickly find errors (like “Syntax error” and “undefined is not a function”) in JavaScript applications. Flow is not a superset language + compiler, but rather just a code checker. Flow gets called by putting //@flow or /* @flow */ at the top of page that needs checking.

If I try the multiply by a string in the example below, Flow calls me out:

Flow tells me Cannot perform arithmetic operation because string [1] is not a number.

Try out flow at the Flow.org playground.

The challenge with Flow is that it will allow common things that JavaScript allows like adding a number and a string (using the aforementioned implicit conversions). That’s to say, Flow will block obviously wrong operations but will let others through like so:

Example in action

This can be fixed by using type annotations (e.g. : number) in Flow. Here’s that example fixed with type annotations:

Dart

Dart is a strongly and staticly typed language (created by Google) that can be compiled to JavaScript. Dart got some notable press 7+ years ago for trying to kill off JavaScript 😆(Google was, at one point, going to put it into the Chrome engine). Recently, Dart has gotten some new momentum as the Flutter ui builder has gained a lot of traction for building native apps (Flutter is built in Dart and uses Dart). Dart, like Swift and Go, was created by a team of whizkids and experts and is meant to offer the best parts of many languages into one.

While Flow and TypeScript feel fairly similar to JavaScript (or in that realm), Dart looks a bit more like C# or Java. Here’s an example from the Dartlang site.

Dart offers some unique typing benefits over Flow or TypeScript. Dart offers static type checking and runtime checks. Types are mandatory but type annotations (e.g. <int>) are optional because Dart performs type inference (it can generally guess the right type).

Why would a developer choose Dart over TypeScript? Many developers/bloggers point out that TypeScript builds upon the advantages/disadvantages of JavaScript. You get the same syntax, data types, and some of the gotchas. Dart, on the other hand, offers a more revolutionary step forward for building fast UIs. Seth Ladd wrote a great list of advantages of Dart over TypeScript:

  • Tree shaking
  • Getters and setters (though I presume TypeScript will get those eventually)
  • Operator overloading
  • Real block scope, no hoisting, no IIFEs
  • A native VM
  • Sane equality semantics
  • No weird implicit conversion craziness
  • Lexically bound this everywhere
  • Mixins
  • Annotations
  • An import system
  • User-defined subscript operators
  • Generics, with reification
  • Mirrors
  • Better collection classes
  • A cleaner DOM API

Should I go strongly and staticly typed? When should I care?

Developer Oliver Zeigermann has a great short list when deciding whether to use a type checker or staticly typed language. If you’re considering going strongly/staticly typed for your next project, run through this checklist:

  • If your project does not live for long: no.
  • If your project is really simple: no.
  • If there is a chance you will need to refactor the thing: yes.
  • If your system is very important or even crucial for the success of your company: yes

For prototyping and playing around, good ol ES5/ES6 are still your go to. But if you’re building things that need to work reliably at scale (and be readable by other developers), it could be worth looking into TypeScript, Flow, or Dart.

 

Kyle Pennell
Kyle Pennell is a marketer and writer with a variety of technical chops (JavaScript, Google Sheets/Excel, WordPress, SEO). He loves clear and helpful copy and likes automating things and making web apps (mostly maps). Found at kyleapennall.com and many other digital spaces