What is Flow for JavaScript?

Publié le - Dernière modification le

JavaScript is a dynamic programming language, and it's very popular. According to the information found on GitHut, most of the new projects created on GitHub are created in JavaScript.

Unfortunately, switching from statically typed programming languages to dynamic programming languages like JavaScript can cause production delays. People need to get used to it and they need to be more attentive to details to avoid issues on static type programming languages, like the lack of a compiler and compile time type checking.

To address this, Microsoft has created TypeScript, a superset of JavaScript that bypasses all the errors encountered when type checking isn't available. Even Angular 2.0 is based on TypeScript, which suggests that TypeScript will be the way to go for JavaScript developers in the near future.

In this article, we will check another statical type analyzer called Flow, which was created by Facebook.

Installation

Flow can only be installed on OSX and Linux, and Windows isn't supported at the moment. It's an open source project, with a current build that can be downloaded from GitHub. Once the final release is downloaded, all you need to do is unzip and add it to your PATH variable using this command:

echo -e "\nPATH=\"\$PATH:FLOW_INSTALLATION_DIRECTORY/\"" >> ~/.bashrc && source ~/.bashrc

Setup and Use

Flow was created in a way that allows it to be added to projects in steps. Adding float to our project and using the analyzer will slow down the development speed, but it will increase the quality of the project. In the case of very small projects, using Flow would be simply waste of time, because its true value appears when the JavaScript code base is large.

To use Flow in your project, it must first be initialized to be Flow-aware. We can do this using the flow init command, which creates a .flowconfig file:

After the init phase, we can check if flow works for the project using the flow command:

We do not have errors at the moment, because we did not set up any file to be scanned by Flow. To activate scanning on a JavaScript code file we have to add a comment at the beginning of the file: /* @flow */.

If we have the following JavaScript code file:

/* @flow */

function addTwice(a,b) {
    return 2 * (a + b);
}

function sumArray(items) {
    var sum;

    for (var idx=0; idx<items.length; ++idx) {
        sum += items[idx];
    }

    return sum;
}

function main() {
    var result = addTwice(13, 22);
    var result2 = addTwice('John', 22);
    var total = sumArray([1,2,3]);
    var total2 = sumArray(['AA', 'CVCss', '123', '5435'])
}

The output of the flow analysis will be:

The first error says that the + operation is not possible for a string and a number. The error appears in the addTwice function, because in the main() function I invoked addTwice using a number and a string parameter.

The next error says that += is not defined for undefined and string values. This happens because in the sumArray function we did not initialize the sum variable, while in the main() method I invoked sumArray() using a string array.

Now let's fix the errors by changing some parts of our code:

function addTwice(a, b) {
    if (typeof(a) === 'number' && typeof(b) === 'number') {
        return 2 * (a + b);
    }
    return 0;
}

function sumArray(items, startValue) {
    var sum = startValue;
    for (var idx=0; idx<items.length; ++idx) {
        sum += items[idx];
    }
    return sum;
}

All we did was add a type check for the addTwice function and initialize the sum variable in the sumArray method.

Adding Types

Flow supports code extension with types. Let's rewrite the code above to use types:

function addTwice(a:number, b:number) {
    if (typeof(a) === 'number' && typeof(b) === 'number'): number {
        return 2 * (a + b);
    }
    return 0;
}

function sumArray(items:Array<number>, startValue:number): number {
    var sum = startValue;
    for (var idx=0; idx<items.length; ++idx) {
        sum += items[idx];
    }
    return sum;
}

Parameter type specification is done similarly in TypeScript, where a semicolon and type name is used. After adding types, the error messages are much more meaningful than before. Before this was done, the analyzer said that the method had errors, but now it shows the exact line where the method is invoked with wrong parameters:

Now we can remove the extra runtime type checks because Flow will do it for us.

/* @flow */

function addTwice(a:number, b:number): number {
    return 2 * (a + b);
}

function sumArray(items:Array<number>, startValue:number): number {
    var sum = startValue;
    for (var idx=0; idx<items.length; ++idx) {
        sum += items[idx];
    }
    return sum;
}

function main() {
    var result = addTwice(13, 22);
    var result2 = addTwice(23, 22);
    var total = sumArray([1,2,3], 100);
    var total2 = sumArray([5435, 44, 432], 100)
}

Since the above code is not standard JavaScript, the type annotations has to be removed from the code. This can be done easily using a transpiler:

npm install jstransform –save (or -g for global availability)

After the transpiler is installed, we need to run it:

This is how Flow can be used. Hope this was able to show you the main workflow required when using a static type analyzer on our JavaScript code. 

Publié 28 août, 2015

Greg Bogdan

Software Engineer, Blogger, Tech Enthusiast

I am a Software Engineer with over 7 years of experience in different domains(ERP, Financial Products and Alerting Systems). My main expertise is .NET, Java, Python and JavaScript. I like technical writing and have good experience in creating tutorials and how to technical articles. I am passionate about technology and I love what I do and I always intend to 100% fulfill the project which I am ...

Article suivant

Customizing Google Maps for Your Projects