JSON to TypeScript
Generate TypeScript interfaces from a JSON sample.
This tool runs entirely in your browser. Your data is never uploaded, never stored, and never leaves your device.
Reads a sample of JSON and writes the TypeScript interfaces that describe its shape, giving each nested object its own named interface rather than inlining everything into one unreadable type.
How to use it
- 1Paste a representative sample — a real API response works better than a trimmed one.
- 2Set the root type name. It defaults to Root, and whatever you type is PascalCased, so "user profile" becomes UserProfile.
- 3Copy the generated interfaces straight into a .ts file.
Example
- Input
- {"id":1,"user":{"name":"Alice"}}
- Output
- interface User { name: string; } interface Root { id: number; user: User; }
Child interfaces take their name from the key and are emitted before the root. Everything is inferred from the sample alone: an array of objects is typed from its first element only, an empty array becomes unknown[], and a null value is typed as null rather than as an optional field — so widen those by hand.
What happens to your data
This tool runs entirely in your browser. Your input is never uploaded to a server, never stored, and never logged. The sample you paste often still contains real IDs, email addresses and tokens, and it is not uploaded.
Last updated August 2026
An endpoint returns a wall of JSON, you need it typed before you can write anything against it, and copying thirty field names out by hand is nobody's idea of an afternoon. Pasting the sample and reading back the interfaces takes seconds, and the result matches the response rather than your memory of it.
Settle one thing first: what the types are for. There are two jobs and they look identical until something breaks. One is a scaffold — you want field names and rough shapes so autocomplete works while you write the calling code, and you tidy the awkward parts as you go. Inference from a sample is good at that. The other is a contract you intend to rely on at runtime, and no sample can give you one: a shape read off one response describes that response rather than promising anything about the next. Where the API publishes an OpenAPI document or a JSON Schema, generate from that instead; where it does not, a runtime validator at the boundary is what makes the type true.
Then choose the sample carefully, because everything is read from it and nothing else. A response carrying an empty list, a null where a nested object usually sits, or one array item the others do not resemble will produce types that compile and then mislead you. Prefer a fat, awkward, realistic response over a tidy one, and expect to widen a few fields by hand afterwards.
How it works
Toolvore parses the sample with the browser's own JSON parser and walks the resulting value, giving every object it meets a named interface and every leaf its TypeScript primitive. Names come from the key the object sat under, PascalCased, so a nested user becomes User; an array of objects takes the key plus Item, so users yields UsersItem. Children are printed above their parent, which puts the root interface at the end. Where a name is taken the next gets a numeric suffix rather than being merged, so two unrelated objects both keyed data become Data and Data2. The weak points all follow from inferring on one sample. An array is typed from its first element alone, an empty array becomes unknown[], and a null is typed as null rather than making the property optional — no question mark is ever emitted. Numbers are all number, dates are strings, and an object used as a dictionary comes back as an interface listing the keys you happened to have. Nothing leaves the page: the parse and the generation both run in your browser.
Common use cases
- Typing a third-party API response before writing the client
- Turning a saved test fixture into interfaces
- Autocomplete on a config file you did not design
- Documenting a webhook payload for a teammate
- Starting a TypeScript migration from real production data
- Checking whether two endpoints return the same shape
Frequently asked questions
What is the difference between an interface and a type alias?+
Both describe an object shape, and either works for output like this. Interfaces can be reopened — declare the same name twice and the members merge, which is how types from a library get extended from outside it. Type aliases cannot do that, but they can name things an interface cannot: unions, tuples, primitives, mapped and conditional types. Most teams settle on interface for object shapes that might be extended and type for everything else. Merging is worth knowing as a hazard too, since a stray second declaration of the same interface name adds fields silently instead of raising an error.
Why is using any for an API response a problem?+
any switches type checking off for whatever it touches, and it spreads — read a field out of an any and that value is any as well, so a typo three functions later still compiles. unknown is the safer stand-in: you can hold it, but you have to narrow it before reading anything off it, which forces the check to exist somewhere. The real cost of any is not the missing autocomplete, it is that the compiler stops telling you when the response changes shape. If you want an escape hatch for one messy field, unknown plus a short type guard keeps the rest of the object honest.
How do I type a field that is sometimes missing?+
Missing and null are different problems, and TypeScript spells them differently. A key absent from some responses is optional — name?: string — which allows the property not to be there at all. A key present holding null is name: string | null, which requires the property but permits null inside it. Inference from a single sample cannot tell the two apart, so this is the usual hand edit after generating. If both happen, sometimes absent and sometimes null, write name?: string | null. None of it is enforced unless strictNullChecks is on, and without it null quietly satisfies every type.
Do TypeScript types check anything at runtime?+
No. Types are erased at compile time and nothing about them survives into the JavaScript that runs. Annotating a fetch result as User does not check the response; it tells the compiler to assume you were right, which is why a field renamed on the backend shows up as undefined in production rather than as a build error. Anything crossing a boundary — HTTP responses, localStorage, query parameters, message queues — deserves a real runtime check. Validators such as Zod or Valibot are the common answer, because one schema gives you both the check and the type, so the two cannot drift apart.
How should I handle dates that arrive as strings in JSON?+
JSON has no date type, so a date arrives as a string and any generator will type it string — accurate, and less useful than you wanted. What to do next depends on the layer. Keep the string if you are passing the value along or rendering it as sent, since a round trip through Date and back can shift a timestamp. Convert to Date where you start comparing or formatting, and do it in one parsing function rather than scattering conversions through the code. Watch date-only strings especially: several runtimes read those as UTC midnight, which lands on the previous day west of Greenwich.
What happens to very large integer IDs in JSON?+
JSON numbers become JavaScript doubles, which hold integers exactly only up to 2 to the 53rd minus 1. A nineteen-digit id from a database or a social platform comes back rounded, and the damage is silent — no error, just an id that matches nothing. The type is not the problem here, parsing is: number honestly describes what you now hold. The fix belongs upstream, which is why several public APIs return both an id and a string version of the same id. If you control neither end, a parser that produces BigInt is the option left, though it changes how the value serialises again.
How do I type an object whose keys I do not know in advance?+
Something used as a dictionary — a lookup keyed by user id, a bag of feature flags — wants Record<string, Value> or an index signature, not a list of whichever keys turned up in your sample. A generator cannot tell the two apart, because a dictionary and a fixed-shape object look identical in JSON, so this is one edit worth making by hand every time. It matters because the generated version errors on any key you did not sample while pretending the ones you did are guaranteed. With noUncheckedIndexedAccess on, reads from a Record come back as possibly undefined, the honest reading.
Is it safe to paste a real API response containing customer data?+
The parsing and the generation both happen inside the page — there is no upload step and no request to a server anywhere in the code — so the JSON stays on your machine. That matters because a real response is exactly what makes generated types useful and exactly what you should not paste into an unknown online converter: it usually carries names, email addresses, internal ids and sometimes a live token. Your clipboard and your browser session are still yours to think about, and if the sample is heading into a bug report, swap the values for fakes first.
Used in these workflows
Related tools
Query String ⇄ JSON
Convert URL query strings to JSON and back.
Number to Words
Spell out numbers in English words, including decimals.
HTML to Markdown
Convert HTML markup into clean Markdown.
Byte Size Converter
Convert between bytes, KB, MB, GB, and their binary (KiB/MiB) forms.