Flow Typechecking Gives Your Code Comments for Free

Setup: Installing Flow is simple. Once installed, to copy-paste the examples in this article, create a new directory and a new .js file. Then run
flow init
in the new directory to initalize the Flow typechecker server. Running
flow
will typecheck all javascript in that directory.

Take this code:


function addOrUpdateItems(payload) {
this.items = this.items.set(payload.id, payload);
}

What does it mean? Given this snippet, how much can you figure out about the larger context of this piece of code?

A big part of software development is reading other people’s code and piecing together a mental model of how it works. This is why we use quality comments — to help with others’ understanding.

Let’s add a quality comment to this snippet:


function addOrUpdateItems() {
// http://facebook.github.io/immutable-js/docs/#/Map/set
this.items = this.items.set(payload.id, payload);
}

By adding a link to some source material, it’s now clear that this.items is an Immutable.js map, saving the inheritor from having to look around in a constructor.

But there’s more you can do to improve the grokking of code than just writing good comments. What about this code?


function addOrUpdateItems(payload: Object): void {
// http://facebook.github.io/immutable-js/docs/#/Map/set
this.items = this.items.set(payload.id, payload);
}

This is code with flow typechecking enabled. Instantly it’s more readable. It’s clear that the payload is an object and this function doesn’t return anything. But what are the attributes that make up the payload object?

Here’s a cool thing about Flow — you can define your own custom types. By defining custom types, you can document more of what is going on with your program to both a human reader of your code and the typechecker, who can help you catch errors.

For example, a feature request rolls in to change to how the addOrUpdateItems function works so that it does something different for each status of the payload, how could we write that only given the information above?

The answer is: we couldn’t. Even though the type annotations are handy, knowing that the payload is an object doesn’t help us all that much. We can guess that there’s an attribute status on that object, but we won’t know the datatype.

But, if we dig deeper with Flow and define a custom type for the payload


type Payload = {
id: number,
status: object,
name: string,
created_at: date,
updated_at: date,
}

function addOrUpdateItems(payload: Payload): void {
// http://facebook.github.io/immutable-js/docs/#/Map/set
this.items = this.items.set(payload.id, payload);
}

Now we’ve documented everything that’s in the payload object and saved ourselves from having to dig around and find out where the payload object receives its status attribute as well as what data type it is (I’ll be you thought status was a string!) Plus we get typechecking for free, so if we call addOrUpdateItems with and incorrect payload from anywhere in our code, we’ll know!

Curious about working with the Revelry team? Learn more about applying to be a part of the crew!