Flow to TypeScript Declarations — Numio
Converts Flow code to TypeScript with flow-to-ts, then emits only a .d.ts declaration file with the TypeScript compiler. Bodies are removed, and parameters with default values become optional.
A package is written in Flow and you want to ship TypeScript typings for TypeScript consumers without migrating the source.
Flow
TypeScript Declarations
When to use it
- A package is written in Flow and you want to ship TypeScript typings for TypeScript consumers without migrating the source.
- You want to compare a Flow module's exported API with its TypeScript equivalent.
How to use
- Paste a Flow module into the Flow panel.
- It is posted to /api/flow-to-typescript with declarationOnly set; the server converts it to TypeScript and emits declarations.
- Copy the result from the TypeScript Declarations panel into an index.d.ts next to your package entry point.
Flow
// @flow
export type Point = { x: number, y: number };
export type Shape = 'circle' | 'square';
export type Label = ?string;
export const ORIGIN: Point = { x: 0, y: 0 };
export function distance(a: Point, b: Point = ORIGIN): number {
return Math.hypot(a.x - b.x, a.y - b.y);
}
export class Canvas {
shapes: Shape[] = [];
draw(shape: Shape, at?: Point): void { this.shapes.push(shape); }
}TypeScript declarations (.d.ts)
export type Point = {
x: number
y: number
}
export type Shape = "circle" | "square"
export type Label = string | null | undefined
export declare const ORIGIN: Point
export declare function distance(a: Point, b?: Point): number
export declare class Canvas {
shapes: Shape[]
draw(shape: Shape, at?: Point): void
}Details and limitations
The page sends your input to a server route (/api/flow-to-typescript) for conversion; it is not processed only in the browser. Next.js API routes accept request bodies up to 1 MB by default.
TypeScript's ES2020 and DOM library files are loaded, so Array<T>, Promise, Date and $ReadOnlyArray (converted to ReadonlyArray) appear in the declarations as written.
Maybe types become T | null | undefined, as with Label in the example.
Only one file is compiled; imported types are not resolved.
FAQ
Are async functions and Promise return types kept?
Yes. export async function load(id: number): Promise<Tag> becomes export declare function load(id: number): Promise<Tag>.
What happens to default parameter values?
They are removed and the parameter becomes optional: b: Point = ORIGIN becomes b?: Point.
Are type aliases kept?
Yes. Exported type aliases appear in their converted TypeScript form. The page formats the result with Prettier, so it uses two-space indentation and no semicolons.