JSON to TypeScript: Generate Interfaces from Any JSON Sample
Free JSON to TypeScript converter — generates interfaces from samples, merging fields into optional props and unions.
Try it now: JSON to TypeScript — Generate TypeScript interfaces from a JSON sample, merging every record so differing keys become optional and varying types become unions.
Why Hand-Writing an Interface From JSON Goes Wrong
You have a real API response — pasted from DevTools, a webhook payload, a database query result — and you want a TypeScript interface for it instead of an any. Typing it out by hand works for a small, flat object; it gets slow and error-prone the moment there's nesting, arrays of records, or a field that's missing here and there. A tool that generates the interface from the actual sample removes both the tedium and the guesswork — provided it gets one detail right, which is the whole point of this guide.
Before generating anything, make sure the sample itself is actually valid JSON — a stray trailing comma or truncated paste will confuse a JSON to TypeScript / JSON to TS generator just as much as it would any other parser. Run it through GenKitLab's JSON Formatter first if you're not sure — see the full JSON Formatter guide for the common syntax errors that break a parse before type generation ever gets a chance to run.
Differing Keys Become Optional, Varying Types Become Unions
The detail that separates a useful generator from a shallow one: when you paste multiple sample records — an array, not a single object — a correct tool merges every record instead of reading the first one and assuming the rest match. A key present in some records but not all becomes optional. A field whose type varies between records becomes a union. Take the first element as gospel instead, and you get types that compile cleanly but lie about the data, and the lie surfaces later, at runtime, as a crash instead of a compile error.
Two near-identical objects make the difference concrete:
[
{ "id": 1, "total": 9.99, "note": "gift" },
{ "id": 2, "total": 12.5 }
]export interface Order {
id: number;
total: number;
note?: string;
}id and total appear in both records, so they stay required. note appears in only the first, so it becomes optional rather than being silently dropped, or worse, required — which would make every order object missing a notefail to type-check even though it's perfectly valid data. Reading only the first array element would have produced a required note and a type that lies the moment a real second order arrives without one.
The same merge logic handles a field whose type outright changes between records:
[{ "v": 1 }, { "v": "x" }, { "v": null }]export interface Row {
v: string | number | null;
}This is why pasting a single object gives you a weaker type than pasting an array of several real records: with one sample, nothing can be marked optional and no union can be detected, because there's nothing to compare it against.
Practical Use Cases
- Typing an API response for a frontend fetch call. Paste the JSON a network tab shows you and get an interface for the fetch client or React Query hook to consume, with nested objects broken out into their own named types.
- A starting point before adding runtime validation. A generated interface only checks shapes at compile time; if you also need to validate the data at runtime — an untrusted API response, a webhook payload — generate a matching Zod schema with JSON to Zod from the same sample.
- Documenting an API's shape for a teammate.A generated interface committed alongside the endpoint it describes is often clearer than a paragraph of prose, and it's always byte-identical for identical input, so regenerating it after an API tweak doesn't create a noisy, unrelated diff.
- Catching a missing or renamed field during a refactor. Regenerate the interface from a fresh sample after a backend change and diff it against the previous version — a field that quietly became optional, or disappeared, shows up immediately instead of at runtime.
If your JSON started life as a spreadsheet export, CSV to JSON is the natural first step — convert the file, then generate types from the array of objects it produces.
Compared to quicktype
quicktype is the most established name in this space, and it's genuinely capable — multiple target languages, a CLI, and a large feature surface for schema-driven generation. That breadth is also why its landing page buries the simple case: paste a JSON sample, generate a TypeScript type from JSON, done in the next ten seconds. If you're looking for a quicktype alternative scoped to just that case, GenKitLab's JSON to TypeScript is scoped to exactly that workflow: paste, merge every sample, get optional fields and unions handled correctly, copy the result — with everything running client-side, so the payload you paste (which is often a real, possibly sensitive API response) never leaves your browser tab.
Frequently asked questions
›How do I generate a TypeScript interface from a JSON sample?
Paste the JSON — ideally an array of several real records, not just one object — and a generator infers the shape: nested objects become their own named interfaces, arrays get an element type, and fields get marked optional or unioned based on how the samples actually differ.
›What happens if my JSON samples have different fields?
A correct generator merges every record in the array rather than reading only the first one. A key present in some records but not all becomes optional; a key present in every record stays required. This is the detail that separates a genuinely useful generator from one that just eyeballs the first object.
›Does it handle nested objects and arrays?
Yes — nested objects are extracted into their own named interfaces rather than left inline, and arrays get an element type derived the same way, by merging every item. Structurally identical nested objects (a billing and a shipping address with the same shape) collapse into a single shared interface instead of two duplicates.
›What if a field is sometimes a string and sometimes a number?
It becomes a union type — string | number — rather than the generator arbitrarily picking one and discarding the other possibility. If some samples had null for that field too, null is added to the union as well.
›Is there a way to also get runtime validation, not just types?
A TypeScript interface only checks shapes at compile time; it does nothing once the code is running. For runtime validation of the same JSON shape — checking an actual API response or webhook payload as it arrives — generate a Zod schema from the same sample with JSON to Zod, which gives you a .parse() call backed by the same field-by-field inference.
›How is this different from quicktype?
quicktype supports more target languages and a CLI workflow, which is real strength for larger, schema-driven projects. GenKitLab's JSON to TypeScript is scoped narrowly to the paste-JSON-get-TypeScript case, runs entirely client-side, and is explicit about merging every sample record for optional fields and unions rather than trusting the first one.
Last updated