Static Type Checking With Flow

A funny thing happens when you mess around with Flow (Facebook’s static type checking library) for a few minutes. JavaScript typing starts to feel simple, useful, and — dare we say? — fun.

See for yourself.

FWIW, Flow is a fine partner for React, but it works like a charm in any JS context.


$ cd into your favorite just-messing project or use the React CLI tool to quickly $ create-react-app something-disposable.

In either case, from the root directory, you’ll want to run the following commands:

$ npm i -D flow-bin
$ flow init

That’s the installation in a nutshell. Install Flow. Create a (for this intro at least) blank .flowconfig file. How you proceed from there is a bit multiple-choice.

  • Did you use create-react-app? Cool. It works with Flow automagically.
  • Using your own Babel config? Run $ npm i -D transform-flow-strip-types and then add "plugins": [transform-flow-strip-types] to your .babelrc to (as the name suggests) strip Flow types from your code.
  • No transpilation? Also cool, but you’ll have to use the special comment syntax mentioned at the end of this article.

The thing to remember is that Flow is just a tool for verifying the integrity of your application. JavaScript interpreters have no clue what to do with its annotations — so they gotta disappear before runtime.


Now that your project has Flow, it’s time to put it to work. First, you’ll want to tag the files you’d like to type check by putting the following comment at the top of each:

/* @flow */

Flow runs a server to keep your checks incremental and running quickly as you change your code. Start it by running $ flow in your project. Now you can perform a check at any point with the same command. You’ll either get the incredibly satisfying No errors! response or a play by play breakdown like this:

Looks like a type mismatch

Flow uses annotations to communicate types. They’re intuitive, but can get as detailed and complex as you’d like. A few examples:

let name: string = "Ol' Bonesnapper";
let age: number = 32;
let hungry: boolean = true;
let faves: string[] = ['tires', 'nutria'];
let eyes: {left: string, right: string} = {left: 'blind', right: 'good'};

Functions behave similarly, but have some curiosities of their own.

function chomp(food: string): string { // We're annotating both the input and the output
  return name + ' ate a ' + food;

Flow also works well with literal values (such as let foodSpecies: 'Myocastor coypus' = 'Myocastor coypus'), classes, and a litany of types exceeding the scope of this primer. The good news is the team did a great job on the docs.

That’s it for the basics.

As to the comment syntax we mentioned above, it will make your Flow annotations invisible to the JS interpreter, which is great if you don’t dig compilation, but it’s kind of a hassle to implement, which is less great if you’re a human. It looks like this:

let name/*: string */= "Ol' Bonesnapper";
let age/*: number */= 32;
let hungry/*: boolean */= true;
let faves/*: string[] */= ['tires', 'nutria'];
let eyes/*: {left: string, right: string} */= {left: 'blind', right: 'good'};
function chomp(food/*: string*/)/*: string*/ {
  return name + ' ate a ' + food;

👉 Word to the wise: Flow is a deep and powerful tool. We've only scratched the surface here, but much of its beauty rests in its "moments to learn, weeks to master" design.

✖ Clear

🕵 Search Results

🔎 Searching...