JSON to TypeScript
Generate TypeScript interfaces from a JSON sample.
About this tool
Paste a JSON response and get TypeScript interfaces for it. Nested objects become their own named interfaces, arrays of objects are merged so optional fields are marked with ?, and mixed values become union types.
How to use it
- Paste a sample JSON response from your API.
- Set the name of the root type, for example User or OrderResponse.
- Choose interface or type declarations, and whether to export them.
- Copy the generated TypeScript into your project and adjust anything the sample couldn’t show.
Questions
- How are optional fields detected?
- When an array contains several objects, a field that is missing from some of them is marked optional with ?. A single object can’t reveal optional fields, so give a sample with several items if you can.
- Why is a field typed as null?
- Because it was null in the sample, so its real type is unknown. Replace it with something like string | null once you know what the API returns.
- Should I use interface or type?
- Both work for describing JSON. Interfaces can be extended and merged and give slightly clearer error messages; type aliases are needed for unions. Pick whatever your codebase already uses.
- Does it validate data at runtime?
- No. TypeScript types disappear when compiled. To check data at runtime, use a schema library such as Zod alongside these types.
- What happens if the JSON root is an array?
- The root becomes a type alias for an array. With the root name User and a sample like [{"id": 1}], you get type User = UserItem[] plus an interface UserItem for the elements. Name the root in the plural, such as Users, to get type Users = User[] instead.
- Can I paste a JavaScript object instead of strict JSON?
- Yes. Single quotes, unquoted keys, trailing commas and Python’s True, False and None are converted to JSON before types are generated, so output copied from console.log in Node or from a Python shell works. Values JSON can’t express, such as functions or class instances, still cause an error.
- Why is an array element type called DataItem?
- Element types are named by making the array’s key singular: users gives User and entries gives Entry. When a key has no plural ending, like data or children, Item is appended instead, which gives DataItem and ChildrenItem. Rename them in your editor after pasting if you prefer other names.
How to generate TypeScript interfaces from JSON
Paste a real API response and every JSON object becomes a named TypeScript interface. Field names are kept, values map to string, number and boolean, and a nested object gets its own declaration named after its key, so an address field produces an Address interface. Arrays of objects are named in the singular: orders gives Order[] and categories gives Category[]. Set the root name to the type your code will use, such as User.
The generated TypeScript compiles as it is, so you can paste it into a types.ts file or download it. Keys that aren’t valid identifiers, such as "first-name" or "2fa", are written in quotes. When two nested objects would get the same name, the second one gets a number, like Address2. An empty array becomes unknown[] and an empty object becomes Record<string, unknown>, because the sample shows nothing about their contents.
How union types are inferred from JSON
When the same field holds different kinds of values, its type becomes a union. An array like [1, "two", null] is typed as (string | number | null)[], and a field that is a string in one item and a number in another becomes string | number. Objects inside the same array are merged into one interface rather than a union of shapes, and fields that appear in only some of them are marked optional.
Merging suits lists of records, but it hides tagged unions. If an events array mixes {"type": "click", "x": 3} and {"type": "key", "code": "Enter"}, you get one Event interface with type as string and both x and code optional. Rewrite it by hand as a discriminated union of two interfaces, one with type: "click" and one with type: "key", so TypeScript can narrow on the type field.
JSON to TypeScript from a sample vs a schema
A JSON sample shows one response, not the contract. Strings that are really dates, enums like "active" | "banned", numeric IDs that may grow past 2^53 and fields that are only sometimes present can’t be seen in a single example. Treat the generated interfaces as a first draft: paste a response with several array items, then tighten the types where you know more, for example replacing status: string with a union of allowed values.
If an API publishes an OpenAPI document or a JSON Schema, generate types from that instead, because it describes every field the server can return. Generating types from JSON is the quick path for third-party APIs without a spec, webhook payloads and old internal endpoints. For data you don’t control, add a runtime check with the same shape, such as a Zod schema, so a changed response fails loudly instead of slipping through.
Something not working, or a result looks wrong? Report a problem with this tool