Flow

A static type checker for JS

Static Type Checker!

JavaScript

// check if a number is even
function isEven(n) {
    return n % 2 === 0;
}

var numbers = [1, 2, 3, 4];

console.log(numbers.filter(isEven)); // [2, 4]

var scores = [10, 22, '4'];

console.log(scores.filter(isEven)); // [10, 22]

Javascript (Flow enabled)

// @flow

// check if a number is even
function isEven(n) {
    return n % 2 === 0;
        
}

var numbers = [1, 2, 3, 4];

console.log(numbers.filter(isEven));

var scores = [10, 22, '4'];

console.log(scores.filter(isEven));
// ^ string. The operand of an arithmetic operation must be a number.

Javascript (Flow with types)

// @flow

// check if a number is even
function isEven(n: number): boolean {
    return n % 2 === 0;
        // ^ string. The operand of an arithmetic operation must be a number.
}

var numbers = [1, 2, 3, 4];

console.log(numbers.filter(isEven));

var scores = [10, 22, '4'];

console.log(scores.filter(isEven));

Promises

  • Code faster
  • Code smarter
  • Code confidently 
  • Code bigger

Getting Started

Installation

// installation
yarn add --dev flow-bin
// initialize flow
yarn flow init
// start it
yarn flow // alias of `yarn flow status`

Usage

// add this comment to the files you want them to be checked
// @flow or /* @flow */
// or use this command to check all javascript files
yarn flow check --all

Types

Annotation

// @flow

function greet(name: string) {
    return `Hi ${name}`;
}

console.log(greet('Mamado'));
console.log(greet(2));
               // ^ number (This type is incompatible with the expected param type of string)

Primitive Types

// @flow

// the literals are written in lowercase
const age: number = 31;
const name: string = 'Soufiane';
const job: null = null;
const family: void = undefined;
const hasACat: boolean = true;

// the constructed value types are capitalized
function doSomeFancyStuff(a: Number, b: String, c: Boolean) {
    // ...
}

doSomeFancyStuff(new Number(1), new String('a'), true);
                                              // ^ boolean (This type is incompatible 
                                              // with the expected param type of Boolean)

Literal Types

// @flow

import * as React from 'react';

// one types
function acceptsTwo(n: 2) {
    // ...
}

acceptsTwo(2);
acceptsTwo(1);
        // ^ number (Expected number literal `2`, got `1` instead number literal `2`)

// using union types
function renderNotification(color: 'red' | 'blue' | 'green') {
    return <div className={`notification ${color}`}></div>;
}

renderNotification('red');
renderNotification('yellow');
                 // ^ string (This type is incompatible with the expected 
                 // param type of string enum)

Other Types

// @flow

function getTypeOf(value: mixed): string { return typeof value } // mixed

function getTypeOf(value: any): string { return typeof value } // any

function getTypeOf(value: ?string): string { return typeof value } // maybe

function getTypeOf(value?: string): string | void { return value && typeof value } // optional

function getTypeOf(...rest: Array<any>): void { // ... } // rest

// object
const obj1: { key: number } = { key: 1 };
const obj2: {
    key: number,
    value: string,
    isValid: boolean,
} = {
    key: 1,
    value: 'super',
    isValid: true,
};

// end many others...

Comment Types

// @flow

/*::
type Args = {
  foo: number,
  bar: boolean,
  baz: string,
};
*/

function method(value /*: Args */) /*: boolean */ {
    return value.bar;
}

method({ foo: 1, bar: true, baz: ['oops'] });
                         // ^ object literal (This type is incompatible with 
                         // the expected param type of object type Property 
                         // `baz` is incompatible:)

Flowify React

PropTypes

// @flow

import * as React from 'react';

type Props = {
  foo: number,
  bar?: string,
};

class MyComponent extends React.Component<Props> {
  render() {
    this.props.doesNotExist;


    return <div>{this.props.bar}</div>;
  }
}

<MyComponent foo={42} />;
            // ^ property `doesNotExist` (Property not found in object type)

State

// @flow

import * as React from 'react';

type Props = { initial: number };

type State = { count: number };

class MyComponent extends React.Component<Props, State> {
    state = { count: this.props.initial };

    componentDidMount() {
        setInterval(() => {
            this.setState({ count: this.state.count + '1' });


        }, 1000);
    }

    render() {
        return <div>{this.state.count}</div>;
    }
}
                                // ^ string (This type is incompatible with number)

Thanks

FlowJS

By Mohammed Erraysy

FlowJS

An introduction to FlowJS

  • 164