JSONParse Open the viewer

Guides

Generate TypeScript types from a real payload

Types written by hand from documentation describe the API someone meant to build. Types generated from a response describe the API that is actually deployed.

How the shape is inferred

The generator walks the indexed document and records, for every object slot, which types were seen and how many of the containing objects had that key at all. A key present in 40 of 40 sampled objects is required; a key present in 31 is emitted as optional. Arrays are unified across their elements, so an array of objects produces one interface rather than a union of near-duplicates.

[
  { "id": 1, "name": "Ada",    "status": "active",   "team": "core" },
  { "id": 2, "name": "Grace",  "status": "inactive" },
  { "id": 3, "name": "Alan",   "status": "active",   "team": "core" },
  { "id": 4, "name": "Edsger", "status": "inactive" }
]

produces

export type Root = RootItem[]

export interface RootItem {
  id: number
  name: string
  status: "active" | "inactive"
  team?: string
}

The bar for a literal union is deliberately high: at least two distinct values, each seen more than once, none of them long, and none of them looking like a formatted value such as a timestamp or a UUID. A wrong enum is worse than no enum, so two records would have produced status: string.

Options

OptionDefaultEffect
Root nameRootName of the top-level type; nested names are derived from keys and singularised.
StyleinterfaceEmit interface declarations or type aliases.
ExportedonPrefix declarations with export.
ReadonlyoffMark every property readonly.
Optional markeronkey?: T when on, key: T | undefined when off.
Literal unionsonEmit a string literal union when a slot behaves like a closed set.
Enum limit12Largest number of distinct strings still treated as a closed set.

Where it is honest about its limits

Inference describes the sample, not the contract. A field that is null in every record in your sample is typed null, because nothing in the data says otherwise. A field that happens to be absent from every sampled object cannot be invented. Treat generated types as a fast, accurate starting point for a document you have, and review them against the API you are coding against.

Generated output carries a provenance header naming the source document, so a file that ends up committed can be traced back to what produced it.

Open the viewerNo sign-up, no upload, no file size dialog.

Frequently asked questions

Does it generate types for the whole file or just what I select?

Either. Generation runs from any node in the tree, so you can type a single nested object out of a very large document without waiting for the whole thing to be analysed.

How are optional properties decided?

By frequency. A key that appears in every object at that position is required; a key that appears in some of them is emitted as optional. With a single object there is nothing to compare against, so every key is required.

Can I run this in CI instead of the browser?

Yes. POST the document to /api/to-typescript, or call the to_typescript tool on the MCP server. Both take the same options as the interface.

Last updated .