Should we use static typing in JavaScript?

Cvetanov Goce
4 min readOct 28, 2017

--

Using static typing in JavaScript has many benefits which you might already know. However, there is one hidden benefit which is not so easy to spot.

Before we mention the hidden benefit which is often overlooked because it is not so obvious, let’s make a short list of all the other benefits static typing offers. The first and probably most evident is:

Compile time error detection

By using static typing, it is much easier for the type checker to detect errors which might occur from wrong parameter types. Here is a snippet for that from the official FlowType getting started guide:

// @flow
function square(n: number): number {
return n * n;
}

square("2"); // Error!

FlowType easily detects that the parameter with which the square function is invoked is not the same type as the function expects and therefore shouts out an error.

Elimination of type checking for input parameters

This might be related to the first one. By using types for your input parameters, you avoid the verbose (and often repeating) logic for ensuring the function is used in the right way. Verifying that the input parameters are in the format the author of the function expects is a not so hard task from a programmer’s perspective so it can, and should, be automated by delegating it to the type checker.

Avoiding verbose documentation

You might have probably seen some not so helpful documentation where only the type of the parameter is written:

/**
* Does some transformation to the given word.
*
* @param {string} foo - The word to transform.
* @returns {string} The transformed word.
*/
function transform(foo) {
// transform `foo` to something
}

The documentation here is not really useful and might take up more lines than the function itself and take away the attention of the developer who is looking up the function. By introducing static typing to the input parameters and the return type of the function, we can omit the documentation altogether moving the focus when reading the snippet to the function itself.

function transform(foo: string): string {
// transform `foo` to something
}

Transition to using immutable objects

Before ES6, var was the only variable type that could be used in JavaScript. After the addition of let and const, we surely are in a better state. Adding custom types of objects using static typing would be the next step to avoid variable reassignments which is a code smell. Using const and custom object types could lead developers to practice immutability and avoid mutating variables which is one of the principles in functional programming. This benefit leads us to the hidden benefit which I mentioned previously.

Performance improvements in V8

V8 is an open source JavaScript engine which is used in Google Chrome and in NodeJS (which covers way more than half of the environments for which JavaScript applications are written). The performance improvement in using static typing for an application which runs on V8 is in the way it handles access to properties on an object. The main motivation for writing this article came after reading an article about how JavaScript works and some insights into the way the V8 engine parses/compiles/optimizes the code. The thing that caught my attention were the hidden classes.

Before reading the mentioned article, I was almost certain that accessing a property on an object is a constant O(1) operation, something like a hash map, and therefore I ended up having lots of commits in our project which were transforming Array.prototype.indexOf() calls to creating an object where the keys would be some id and just looking up the value from the created object. As it turns out, due to JavaScript being a dynamically typed language, this might not always be the case.

Hidden classes in V8 are responsible for accessing properties of objects. For every property added to an object, a new hidden class is created which contains info about where can that property be found (associates an offset to a property). So if we have two objects which represent a person, but their properties are assigned in a different order, accessing the properties on these objects might not behave in the same way due to the different hidden classes which got created (different offsets for the properties). Consider the following snippet:

function Person(name, age) {
this.name = name;
this.age = age;
}
const player = new Person('Jane', 22);
const referee = new Person('Joe', 22);
// here both variables have a shared hidden class
referee.nationality = 'Germany';

Up until the assignment of nationality to the referee both variables were sharing the same hidden class generated by V8 so the engine has generated optimized assembly code for accessing and assignment of properties on the player and referee variables. When a new property was introduced, V8 ends up generating a new hidden class for the referee object and therefore accessing properties on objects of the allegedly same class will be done in different ways which will add some overhead to it.

By using static typing, the type checker supplies enough information to the compiler of what are the available properties an object can have which will make it easier for the engine to generate shared hidden classes for all objects of that type and optimize the generated assembly for accessing/modifying those properties.

Summary

Taking into consideration all the advantages mentioned above, static typing is something which should seriously be considered when starting a new project in JavaScript. The only disadvantage I could think of to introducing static typing to your project and your team is that it will be yet another thing to learn for your colleagues.

So the question you should be asking is not “Why should we use static typing?”, but “Why are we not using static typing?”.

--

--