Flow Formatter Online — Format Flow Type Annotations

Beautify JavaScript with Flow type annotations — type aliases, generic constraints, opaque types, exact object types, and FlowFixMe directives — 100% in your browser.

What is a Flow Formatter?

A Flow formatter rewrites a Flow-typed JavaScript file with consistent indentation and brace placement. Flow extends JavaScript with type annotations, type aliases (type X = ...), opaque types (opaque type Id:number=number), exact object types ({| field: T |}), variance annotations (+read, -write), generic constraints (T: Comparable), and the // @flow pragma at the top of the file. The formatter handles all of this as standard brace-and-indent layout because Flow syntax is a strict superset of JavaScript.

The OpenFormatter Flow tool runs entirely in your browser; nothing is uploaded. Use it for a one-off readability pass on a Flow file copied from a code review, a Stack Overflow answer, or a third-party Meta open-source project (React itself is Flow-typed internally and ships .flow.js declaration files).

How to format Flow code — 4 steps

  1. Paste your Flow code. Drop a // @flow file body — type aliases, generics, classes, opaque types — into the Input panel. Click Load Sample to try a generic-heavy demo with exact object types.
  2. Click Format. The formatter rewrites brace placement and indentation client-side and emits one statement per line.
  3. Review the output. Confirm exact object types, opaque types, and class methods are readable.
  4. Copy the result. Click Copy to paste into your editor, a PR description, or a GitHub issue.

Side-by-side: dense input vs formatted output

Compact Flow

// @flow
type User={|+id:number,+name:string,email:?string,roles:Array<'admin'|'user'>|};
type Result<T,E=Error>={|ok:true,value:T|}|{|ok:false,error:E|};
opaque type UserId:number=number;
function fetchUser<T:UserId>(id:T):Promise<Result<User>>{return fetch(`/api/users/${(id:any)}`).then(r=>r.json()).then((value:User)=>({ok:true,value})).catch((error:Error)=>({ok:false,error}));}
class Cache<K,V>{store:Map<K,V>=new Map();get(k:K):?V{return this.store.get(k);}set(k:K,v:V):void{this.store.set(k,v);}}
const u:User={id:1,name:'Jane',email:null,roles:['admin']};

Formatted Flow

// @flow
type User = {| +id: number, +name: string, email: ?string, roles: Array<'admin' | 'user'> |};
type Result<T, E = Error> = {| ok: true, value: T |} | {| ok: false, error: E |};
opaque type UserId: number = number;
function fetchUser<T: UserId>(id: T): Promise<Result<User>> {
  return fetch(`/api/users/${(id: any)}`).then(r => r.json()).then((value: User) => ({ ok: true, value })).catch((error: Error) => ({ ok: false, error }));
}
class Cache<K, V> {
  store: Map<K, V> = new Map();
  get(k: K): ?V {
    return this.store.get(k);
  }
  set(k: K, v: V): void {
    this.store.set(k, v);
  }
}
const u: User = { id: 1, name: 'Jane', email: null, roles: ['admin'] };

Flow-Aware

Handles type aliases, opaque types, exact object types {| ... |}, variance annotations (+/-), and generic constraints.

Compilation Unchanged

Whitespace outside string contexts does not affect Flow checking or Babel emit. Formatted and unformatted source produce identical JavaScript.

Browser-Only

Flow code runs through JavaScript on your machine. Source files with internal type definitions and FlowFixMe ticket references stay on the device.

Common use cases

  • check_circleFormat a Flow file before checking in to a Meta-style monorepo
  • check_circleReformat dense Flow type definitions copied from a GitHub issue or PR
  • check_circleClean up auto-generated Flow types from a code generator
  • check_circleIndent a React.Component<Props, State> class with many type parameters
  • check_circleFormat a .flow.js declaration file for a third-party library
  • check_circleReformat Flow types extracted from React Native's internal source
  • check_circleBeautify a $FlowFixMe-heavy legacy file before a type-strictness migration
  • check_circleFormat a one-line opaque type chain pasted from a Flow Try Out share link

Flow formatter vs Prettier vs flow-format-comments

A pretty printer is the lightweight option — it preserves token order and only adjusts whitespace. Prettier with the babel-flow parser goes further: it parses the file, applies width-aware re-printing, and normalises quote style, trailing commas, and arrow-function parens. flow-format-comments (and similar tools) target a narrow problem: converting Flow comment-syntax types (/* :T */) into native syntax for files that need to ship to environments without a Flow stripper. Use this online tool for a one-off readability pass; use Prettier for project-wide enforcement.

More than Flow formatting

Format TypeScript, generate Flow types from JSON, or pretty-print JavaScript — all browser-side.

Frequently Asked Questions

Is Flow still maintained?

Yes — Flow is actively developed by Meta (Facebook) and used in their largest internal codebases including the Meta web stack and React. The public release cadence is steady (multiple releases per year), and 2023–2024 saw major work on Flow Local Type Inference (LTI), which significantly improved inference quality. Flow is no longer the obvious default for new projects — TypeScript has won that mindshare — but it is not deprecated, abandoned, or unsupported. If you maintain a Flow codebase you can rely on Meta's continued investment.

Flow vs TypeScript — what is the practical difference?

Both add static types to JavaScript. TypeScript has the larger ecosystem (DefinitelyTyped, library types shipped in node_modules, every major editor has TS support out of the box), VS Code as its reference editor, and a much larger community. Flow has stronger type narrowing in some cases, exact object types ({| ... |} that disallow extra properties — TS got this with stricter literal types but the syntax differs), variance annotations on properties (+read, -write), opaque types (true nominal types), and tighter integration with the Babel transpiler used at Meta. For new projects, TypeScript is the conventional choice. For existing Flow codebases, migration to TS is possible but non-trivial — and not always necessary.

Does this formatter understand Flow-specific syntax?

It is brace-aware, not Flow-AST aware — but Flow syntax is a strict superset of JavaScript so the brace-and-indent rules apply directly. Type aliases (type X = ...), opaque types (opaque type Id:number=number), exact object types ({| field: T |}), generic constraints (T: Comparable), and variance annotations (+read, -write) all format correctly because they are tokens between braces, not new structural elements. The output is consistent indentation; for full re-printing of complex generic constraints use Prettier with the babel-flow parser.

Will it preserve // @flow pragmas and $FlowFixMe directives?

Yes. Comments are preserved verbatim including the file-header // @flow pragma (which marks a file as Flow-checked), $FlowFixMe[error-code] suppression comments above lines, $FlowExpectedError[code] for tests, and $FlowIgnore. Removing or moving these would change checker behaviour, so the formatter never touches them.

Does it handle React.Component<Props, State> patterns?

Yes. class MyComponent extends React.Component<Props, State> formats as a generic class declaration with the type parameters preserved. Props and State type aliases above the class indent normally. The render() method returns React$Node or React.Node depending on Flow version — both are formatted as ordinary type annotations on the method signature.

How does it handle nullable types (?T) and maybe types?

Flow uses ?T to mean T | null | void (a maybe type that includes both null and undefined), distinct from T | null. The formatter preserves the ? prefix exactly as written. Inside generic constraints, function return types, and class field declarations, the ? marker stays adjacent to its type — there is no space inserted between ? and the type name.

Will this format correctly for files using both Flow and JSX?

Yes — Flow JSX (.js files with // @flow and JSX, no extension change) is just JavaScript with extra type annotations. The brace-aware formatter follows the surrounding curly braces, so a return ( <Component prop={value: string} /> ) gets indented as a function body and the JSX is left intact. For deeper JSX-specific reformatting (attribute wrapping, self-closing normalisation), Prettier remains the better choice.

Is the Flow code I paste sent to your servers?

No. Formatting runs entirely in your browser using JavaScript. Source files containing internal Meta-specific or proprietary type definitions, $FlowFixMe suppressions referencing JIRA tickets, or unreleased features never leave your device. Open DevTools → Network and click Format to verify no requests are made.

Flow Formatter — Format Flow Type Annotations