Getting started
Typeflow lets you write JSON transformations in .typeflow files that TypeScript actually understands — input paths are validated, output types are inferred, and mistakes fail your build instead of your production traffic.
Install
One package, no extra setup — works with plain Node (≥ 18), npm, pnpm, or Bun:
$ npm i typeflowjsPre-release
Typeflow is pre-1.0: syntax and APIs are unstable by design, and the package is not yet published to npm. Clone the repository to try it today.
Your first mapping
Scaffold an example:
$ npx typeflow init
Created user-types.ts, user.typeflow.user.typeflow binds its input to an exported TypeScript type and mirrors the output shape:
input user: User from "./user-types"
map {
id: user.id,
fullName: user.firstName + " " + user.lastName,
email: user.contact?.email ?? "unknown",
activeTags: user.labels[active].name,
}Check it, inspect the inferred output, run it:
$ npx typeflow check user.typeflow
✔ 1 mapping(s) checked, 0 errors.
$ npx typeflow infer user.typeflow
{ id: number; fullName: string; email: string; activeTags: string[] }
$ echo '{"id":1,"firstName":"Ada","lastName":"Lovelace","labels":[]}' | npx typeflow run user.typeflowUse it from code
loadTypeflowMapping compiles the file, resolves its TypeScript types, imports any use functions, and returns a ready mapping function:
import { loadTypeflowMapping } from 'typeflowjs';
const mapUser = await loadTypeflowMapping('./user.typeflow');
const view = mapUser(apiResponse);For hot paths, compile once and serialize: the compiled artifact is plain JSON, and typeflowjs/runtime is a tiny dependency-free interpreter you can ship alone (it even runs in the browser — the playground is exactly that).
import { compile } from 'typeflowjs';
import { createMapping } from 'typeflowjs/runtime';
const { compiled } = compile(source, { fileName: 'user.typeflow' });
const mapUser = createMapping(compiled!);Typed imports
Generate declarations and enable allowArbitraryExtensions:
$ npx typeflow types
generated user.d.typeflow.ts// tsconfig.json
{ "compilerOptions": { "allowArbitraryExtensions": true } }TypeScript now understands import mapUser from "./user.typeflow" — with full input/output types.
CI
$ typeflow check && typeflow types --checktypes --check fails if committed declarations have drifted from the mappings.