Developer Tools
JSON to TypeScript
JSON to TypeScript is part of Toolspire and is ready as soon as this page loads. Paste an API response and get TypeScript interfaces, type aliases or Zod schemas as you type. Optional properties, unions and nested types are worked out from the data, and nothing is uploaded.
On this page
What you can do here
Three output styles
interface, type or a Zod schema with its inferred type. Switch between them without pasting again.
Optional properties found for you
Paste a list of records and every property that is missing from some of them is marked with ?, with the paths listed below the result.
Readable type names
Types are named from their keys and list items in the singular: categories gives Category[]. Name clashes are resolved, and names that would hide built-ins like Date are avoided.
Honest about gaps
A null or an empty list tells nothing about the real type. Those places are listed so you can fill them in, rather than hidden behind any.
Your conventions
Choose the root name, export, readonly, all-optional properties, inline or named nested types, and 2 spaces, 4 spaces or tabs.
Private
Responses with tokens, customer data or internal fields stay on your device. Nothing is sent to a server.
The sequence
How to convert JSON to TypeScript
- 1
Add your JSON
Paste a JSON object or array — an API response, a config, a database record — or click Open file.
- 2
Pick the output
Choose Interface, Type or Zod schema, and set the root type name under Options.
- 3
Read the notes
Below the result, check which properties were made optional and which values had no type to infer.
- 4
Copy or download
Copy the code into your project or download it as a .ts file.
Worth knowing
- JSON to TypeScript on Toolspire: turns JSON into TypeScript interfaces, type aliases or Zod schemas with inferred types, straight away as you type.
- Every object in a list is combined into one type: a property missing from some objects becomes optional (
coupon?: string), and a value seen with several types becomes a union (string | number). - Nested objects get their own named types taken from their keys —
address→Address,orders→Order[]— or are written inline. Places with the same name and structure share one type. - Objects whose keys are IDs or dates, such as
{"1042": {…}, "1043": {…}}, are typed asRecord<string, …>instead of one property per ID. - What the sample cannot show is reported instead of guessed: a value that is always
nullis typednull, and an empty listunknown[], each listed with its path. - Zod output declares every schema before it is used and adds a
z.infertype for each one. - Accepts JSON with comments, trailing commas and single quotes, and points to the exact line and column of real errors.
- Runs in this tab: the API responses you paste are not sent to us.
How JSON values become types
| JSON | TypeScript | Zod |
|---|---|---|
"name": "Asha" | name: string | z.string() |
"id": 1042 | id: number | z.number() |
"active": true | active: boolean | z.boolean() |
"roles": ["admin"] | roles: string[] | z.array(z.string()) |
"address": {…} | address: Address | addressSchema |
| in some objects only | coupon?: string | z.string().optional() |
text in one object, null in another | note: string | null | z.string().nullable() |
| a number in one object, text in another | value: string | number | z.union([z.string(), z.number()]) |
"avatar": null every time | avatar: null | z.null() |
"tags": [] | tags: unknown[] | z.array(z.unknown()) |
"extra": {} | extra: Record<string, unknown> | z.record(z.string(), z.unknown()) |
Getting better types
- Paste a list of several records rather than one. Optional properties and unions can only be found by comparing objects.
- Include a record where nullable fields have a value, so
avatar: nullbecomesavatar: string | null. - Types come from the sample, not from the API’s rules. A property present in every sample is typed as required even if the API may omit it — use Make every property optional for partial data.
- Dates, emails and URLs are strings in JSON, so they are typed
string. Add stricter checks in your Zod schema where you need them. - Property names that are not valid identifiers, such as
last-login, are written in quotes:'last-login': string.
Interface, type or Zod?
An interface and a type describe the same object shape; use whichever your codebase prefers. Both exist only while compiling and add nothing to the code that runs.
A Zod schema also checks data at run time. Parse an API response with it and you get an error when the response does not match, plus the TypeScript type from z.infer — so the type and the check never drift apart. The generated code needs the zod package in your project.
FAQ
Questions about JSON to TypeScript
Where does JSON to TypeScript run?
Is my JSON uploaded anywhere?
How does it decide a property is optional?
?. With a single object there is nothing to compare, so every property is required.Why is a property typed null or unknown[]?
null, or only an empty list, at that place, so the real type cannot be known. The tool lists these paths below the result. Paste a sample with real values there, or edit the type by hand. Turn on Use any where the type is unknown if you prefer any.Can it generate a Zod schema?
z.object(…) schemas with .optional(), .nullable(), unions, arrays and records, each followed by its z.infer type. Nested schemas are declared before the ones that use them, and the code runs on both Zod 3 and Zod 4.How are the types named?
shipping_address becomes ShippingAddress. Items of a list use the singular (orders → Order). If two different structures would get the same name, the parent’s name is added, as in OfficeAddress.What about an object with IDs as keys?
Record<string, …>, with the values combined into one type.Can I paste JSON with comments or trailing commas?
Keep going
Related tools
Last updated Report a problem or suggest a feature