Paste or upload JSON
Add any JSON object or array to the input panel. Use the sample button to load a realistic API response with nested objects and arrays.
Convert JSON objects and API responses into TypeScript interfaces instantly. Nested objects become named interfaces, arrays of objects produce typed generics, and you can export type aliases or interfaces, all client-side with zero upload.
Generating TypeScript from JSON is structural inference. The generator walks the value, and at every node it asks what shape this is: an object becomes an interface with one member per key, an array becomes an element type followed by square brackets, and a primitive becomes string, number, or boolean.
For an array of objects, the generator does not stop at the first element. It merges every element to build one type that describes all of them, which is what makes optional properties and unions possible. Nested objects become their own named interfaces rather than inline literals, because named types produce far more readable errors and can be imported individually.
A paginated API response and the interfaces it produces.
JSON response
Generated TypeScript
Two keys picked up a question mark because they were present in one result and absent in the other. And next_cursor was typed as null, which is almost certainly wrong: see the caveat section.
| Situation | Prefer | Reason |
|---|---|---|
| Describing an object shape | interface | Idiomatic, and error messages name the interface |
| A public API surface others extend | interface | Declaration merging lets consumers augment it |
| A union of several shapes | type | Interfaces cannot express a union |
| A primitive or tuple alias | type | Interfaces only describe object shapes |
| A mapped or conditional type | type | Only type aliases support these operators |
| Anything recursive | Either | Both handle self reference correctly |
The practical difference is smaller than the debate around it suggests. Object shapes as interfaces and everything else as type aliases is a rule that never causes friction.
The interesting inference happens when records disagree with each other.
Under strictNullChecks, which every project should have on, null and undefined are not assignable to other types. That is what makes the optional versus nullable distinction enforceable instead of decorative. A field typed string | null forces you to handle the empty case at the point of use, which is the entire value of the exercise.
Types generated from a sample describe that sample. They do not describe the API contract, and the difference between those two things is where the bugs live.
| What the sample showed | What was generated | What is actually true |
|---|---|---|
| next_cursor was null | next_cursor: null | string | null once there is a next page |
| Every user had a locale | locale: string | Optional, absent for new accounts |
| status was always active | status: string | A closed union: "active" | "suspended" | "closed" |
| tags was an empty array | tags: unknown[] | string[] |
| No error object appeared | Not present at all | Returned on every failure path |
| id looked numeric | id: number | Sent as a string by the API in some regions |
Treat the generated file as a first draft that saves you the typing, then read the API documentation and correct it. Pay particular attention to fields that were null or empty in your sample, enumerable status fields that deserve a literal union, and every error shape, because error responses are almost never in the happy path sample you copied.
TypeScript types are erased during compilation. Nothing checks that the JSON arriving over the network actually matches the interface you wrote, and a response that has changed shape will flow straight into code that assumes otherwise.
A type assertion is a promise, not a check
Runtime validation libraries such as Zod, Valibot, io-ts, and ArkType let you declare the shape once and get both a runtime check and a static type from it. For anything crossing a trust boundary, which means network responses, form input, webhook payloads, and files on disk, that is worth the small amount of extra code.
Types are one way to pin down a payload's shape. Look at the full converter collection for JSON Schema when you need runtime validation rather than compile time types, JSON to GraphQL when the same shape needs an SDL definition, and JSON to SQL when it needs a table to live in.
Add any JSON object or array to the input panel. Use the sample button to load a realistic API response with nested objects and arrays.
Choose interface or type alias, toggle key sorting, and set the root interface name to match your codebase convention.
Interfaces update live as you type. Copy the output or download a ready-to-import .ts file.
Stop writing interfaces by hand. Paste a JSON API response and get typed interfaces in seconds, ready for your TypeScript project.
Your JSON never leaves the browser. No upload, no server, no logs.
TypeScript interfaces update as you type with clear error messages for invalid JSON.
Objects within objects each get their own named interface in PascalCase.
Arrays of objects produce a typed item interface and a typed array alias.
Toggle between interface and type alias declarations to match your project style.
Export all generated interfaces as a ready-to-import TypeScript file.
This tool infers TypeScript types from JSON values: strings become string, numbers become number, booleans become boolean, and null becomes null. Objects generate named interfaces derived from the property key in PascalCase. Arrays of objects merge all item shapes and produce a typed item interface. You can switch to type aliases, sort keys alphabetically, and rename the root interface to match your project conventions.