Flow is a static type checker for JavaScript designed to catch errors before code runs.
Getting Started
Simple Example
/* @flow */
function square (n: number): number {
return n * n
}
const four = square(2)
Annotate function parameters and return values with Flow types.
See: Flow Documentation
Type Inference
function square (n: number) {
const result = n * n
}
result is inferred as number because number * number produces a number. Explicit annotations are optional when Flow infers types automatically.
Type Aliases
type Person = {
name: string,
age: number,
isAdmin: boolean,
likes: Array<string>
}
function greet(user: Person): string {
return `Hello ${user.name}`
}
Use type Name = ... to declare reusable structural object types.
Variable Annotations
const count: number = 42
let message: ?string = null
Usually variables do not require explicit annotations; Flow derives them from assigned values.
Modules: Import & Export Types
// Exporting a type
export type UserID = string;
// Importing a type
import type { UserID } from './types';
import typeof Component from './Component';
Union Types
type Status = "pending" | "fulfilled" | "rejected";
type ID = string | number;
Optional & Nullable Types
Maybe Types (?Type)
type Response = {
data: ?string // string, null, or undefined
}
Prefixing a type with ? allows null or undefined alongside the underlying type.
Optional Object Properties (key?: Type)
type User = {
name: string,
nickname?: string // property may be omitted from object
}
Optional properties can be absent entirely from the object keys, distinct from having a null value.
Objects
Width Subtyping
type Named = { name: string }
type Person = { name: string, age: number }
const p: Person = { name: "Alice", age: 30 }
const n: Named = p // Valid: Person is a subtype of Named
Flow objects by default allow extra properties beyond the declared shape.
Exact Object Types ({| ... |})
type ExactUser = {|
name: string,
age: number
|}
// Error: extra property 'role' not allowed in exact object
const u: ExactUser = { name: "Bob", age: 25, role: "admin" }
Enclose keys in {| ... |} to disallow unlisted excess properties.
Indexers / Dynamic Keys
type Cache = {
[key: string]: number
}
const scores: Cache = { alice: 100, bob: 95 }
Advanced Types
Primitives & Structure Table
| Type | Description |
|---|---|
boolean |
true or false |
number |
Floating point numbers and integers |
string |
Text string |
null |
Only literal null |
void |
Only undefined |
mixed |
Top type: safe arbitrary value, requires refinement |
any |
Unchecked escape hatch: disables type safety |
Array<T> / T[] |
Array containing elements of type T |
[string, number] |
Tuple: fixed length and positional types |
| `{ | k: T |
?T |
Maybe type: T, null, or void |
A | B |
Union type: matches either A or B |
A & B |
Intersection type: matches both A and B |
Generic Classes & Functions
class Container<T> {
value: T;
constructor(val: T) {
this.value = val;
}
get(): T {
return this.value;
}
}
const box = new Container<number>(123);
Interfaces
interface Printable {
print(): string;
}
class Document implements Printable {
print(): string {
return "Printing doc";
}
}
Flow Comments Syntax (No Transpilation Needed)
/*::
type CustomConfig = {
timeout: number
};
*/
function fetchWithTimeout(url /*: string */) /*: Promise<Response> */ {
// ...
}
Use /*:: ... */ to embed Flow types in vanilla JS files that run in browsers or Node without Babel stripping.