Flow is a static type checker that helps you write code with fewer bugs. Flow allows you to incrementally add types to your JavaScript code to perform type-checking.
You need to tell Flow which files to type-check, for this you add a // @flow
comment at the top of the file.
Once you’ve declared a file to check, you can use the Flow syntax in that file to define types.
yarn run flow
will type-check the project based on the.flowconfig
file.yarn run update-types
updates the Library Definitions.
Library definitions (AKA "libdefs") are files that inform flow of the type signature of third-party packages.
They are .js
files placed in the flow-typed
directory.
flow-typed is used to install pre-existing libdefs, it is analogous to TypeScript's DefinitelyTyped.
You can add types for Javascript primitives, as well as Array, Object and other constructs:
const isLogged: boolean = false;
const userId: number = 1234;
const userName: string = 'Mark';
const data: null = null;
const undefined: void = null;
const arrayOfNumbers: Array<number> = [1, 2, 3];
const userData: { name: string, id: number } = {
name: 'Mark',
number: 1234,
}
const sum = (a: number, b: number): number => {
return a + b;
}
One of the most useful features is type aliasing. They allow you to use existing types to create new types:
type Transaction = {
id: number,
description: string,
value: number,
};
Generics allow you to abstract over types:
type GenericObject<T> = { key: T };
const numberObject: GenericObject<number> = { key: 1234 };
const stringObject: GenericObject<string> = { key: "text" };
A question mark is used to represent Maybe types, they represent a potentially null
or undefined
value:
const stringOrNull: ?string = null;
There are other useful type definitions like Union Types and Utility Types, you can find them in the documentation.
Flow has very good support for React. This sections explains some common patterns to type React code.
The React.Component
class takes two type arguments, Props
and State
. You can use them as replacement of
PropTypes
, which was the recommended way to type check React components.
type Props = {
foo: number,
};
type State = {
bar: number,
};
class MyComponent extends React.Component<Props, State> {
state = {
bar: 42,
};
render() {
return this.props.foo + this.state.bar;
}
}
If the component doesn't have state, you can just pass <Props>
.
Flow includes utility types which can be useful to type complex React pattern. The most important ones are:
React.Node
, represents any value that can be rendered by React. It can be a string, number, boolean, null, or React element.React.ComponentType<Props>
, is the type of any class component or stateless function component. This is useful as an input type for Higher Order Functions.React.Element<Type>
, is the type of a React element.
Note: React must be imported as a namespace (import * as React from 'react'
), this way you get access to React's
utility types.
Stateless functional components are typed like regular functions:
type Props = {
bar: string,
};
function MyComponent(props: Props) {
return <div>{props.bar}</div>;
}
Typing Redux state works like typing any other object in Flow:
type State = {
users: Array<{
id: string
name: string,
}>,
activeUserID: string,
// ...
};
Redux state is meant to be immutable: you should creating a new state object instead of changing properties on it. You can enforce it with Flow by making every property "read-only" using "covariant" properties like this:
type State = {
+users: Array<{
+id: string
+name: string,
}>,
+activeUserID: string,
// ...
};
You can use disjoint unions to type all actions supported by a reducer:
type FooAction = { type: "FOO", foo: number };
type BarAction = { type: "BAR", bar: boolean };
type Action =
| FooAction
| BarAction;
This way you can use the individual action types to type action creators, and the general Action
type to type the
reducer.
Reducers take and receive the state and actions we have previously defined:
function reducer(state: State, action: Action): State {
// ...
}
Check the documentation for more detailed information.