Logo

MonoCalc

/

JSON to TypeScript

Programming

1 sample · 4 types · 2 notes

JSON input

Paste several responses one after another, or a JSON Lines file, to merge them into one type.

TypeScript

[]Order: click to show it in the outputOrderrootid: numberidnumberstatus: stringstatusstringplacedAt: stringplacedAtstringcustomer: CustomercustomerCustomeritems: Item[]itemsItem[]couponCode: unknowncouponCodeunknowntags: unknown[]tagsunknown[]Customer: click to show it in the outputCustomername: stringnamestringemail: stringemailstringshipping_address: ShippingAddressshipping_addressShippingAddressShippingAddress: click to show it in the outputShippingAddressline1: stringline1stringcity: stringcitystringpostcode: stringpostcodestringItem: click to show it in the outputItemsku: stringskustringtitle: stringtitlestringqty: numberqtynumberprice: numberpricenumbergiftWrap?: boolean (present in 1/2)giftWrap?boolean1/2

Each box is a declared type. Optional fields show how many of the objects seen had them. Click a box to find it in the output.

Everything runs in your browser. The JSON is never uploaded or stored; only the options are remembered on this device. Live updates run up to 1 MB; from 1 MB to 5 MB, generate on paste, on load or with Ctrl/Cmd+Enter.

To use an API response, paste it here. In browser devtools: Network → right-click the request → Copy response.

Not included: runtime validators (Zod, io-ts, JSON Schema), other languages, discriminated-union detection, renaming properties to camelCase, and loading JSON from a URL.

About This Tool

JSON to TypeScript – Generate Interfaces from Real API Responses

Typing an API response by hand is slow and easy to get wrong. This JSON to TypeScript converter reads a sample of real data, such as an API response, a config file or a log line, and writes the TypeScript interfaces that describe it. Each nested object gets its own named declaration. Arrays, unions, optional properties and null are all worked out from the data. The result is ready to paste into your codebase, and all of it runs in your browser.

From one sample to many: how the types are inferred

The generator folds every value it sees into a shape: one record per position in the document that counts how often each kind of value appeared. All items of an array share one shape, so a list of 500 orders becomes a single Order type, not 500. You can also paste several responses one after another, or a JSON Lines file (.jsonl, .ndjson), and they are merged the same way. More samples give more accurate types.

  • A key that some objects lack becomes optional: giftWrap?: boolean.
  • A value that is sometimes null becomes T | null. Missing and null are different at runtime, so the tool keeps them apart. A key that is both prints as phone?: string | null.
  • Mixed values become a union in a fixed order, for example string | number, so the output stays the same when you reorder your samples.
  • Objects keyed by numeric IDs, UUIDs or dates are detected as maps and typed as Record<string, User> instead of an interface with one property per ID.

Readable names, no clashes

Type names come from property keys. shipping_address becomes ShippingAddress, and the items of an array are singularized, so line_items becomes LineItem and categories becomes Category. When two different shapes ask for the same name, the second one is prefixed with its parent (CompanyAddress). Names that would clash with built-in types such as Date, Response or Event are prefixed too, because an interface Date in a script silently merges with the global Date. Identical shapes share one declaration, and any type can be renamed in the Types tab. Every reference follows the new name.

Property names are never changed
The tool keeps shipping_address as it is instead of converting it to camelCase. A renamed property would describe an object that JSON.parse never returns.

See the structure, then check the gaps

The type diagram draws each declared type as a box, with arrows to the types it references. Optional fields show their coverage, for example 1/2, meaning the key appeared in one of the two objects seen at that position. That answers the usual question "why is this optional?". The Notes tab lists what a person should review before trusting the output:

  • Fields that were null in every sample and arrays that were always empty. These are typed unknown because the data says nothing about them.
  • Fields that mix types, such as an ID that is sometimes a number and sometimes a string.
  • Integers above Number.MAX_SAFE_INTEGER (9007199254740991), such as 64-bit IDs, which JSON.parse silently rounds. They also get a JSDoc warning in the output.
  • Duplicate keys, detected maps and types renamed to avoid a clash.

Output options

Choose interface or type declarations, separate or inline nested types, T[] or Array<T>, readonly properties, 2 or 4 spaces or tabs, and unknown or any for fields with no information. You can also add example values as JSDoc comments, or turn enum-like strings into literal unions such as "admin" | "editor". Comments and trailing commas, common in tsconfig.json-style files, are accepted by default.

Types are only as good as your samples
Generated types are a starting point and are checked at compile time only. A field your samples never contained, or an enum value they never used, will not appear. For checks at runtime, add a validation library to your project.

Frequently Asked Questions

Is the JSON to TypeScript free?

Yes, JSON to TypeScript is totally free :)

Can I use the JSON to TypeScript offline?

Yes, you can install the webapp as PWA.

Is it safe to use JSON to TypeScript?

Yes, any data related to JSON to TypeScript only stored in your browser (if storage required). You can simply clear browser cache to clear all the stored data. We do not store any data on server.

How does the JSON to TypeScript generator work?

It reads every value in your JSON, merges all samples and all array items that sit at the same position into one shape, and prints a named interface for each nested object. Optional properties, null, unions, maps keyed by ID and reused shapes are all worked out from the data, entirely in your browser.

Why is a property optional (?) in one place and | null in another?

Missing and null are different at runtime. A key that some objects don't have becomes key?:, while a key that is present but sometimes null becomes T | null. When both happen, you get key?: T | null.

Why does it say unknown instead of guessing a type?

A field that was null in every sample, or an array that was always empty, carries no type information. Rather than guess, the tool writes unknown (or any, if you prefer) and lists it under Notes. Add a sample where the field has a value to get a real type.

Should I use interface or type?

Both describe the same object shapes and work the same for API data. Interfaces can be extended and merged; type aliases can also name unions and arrays. Pick whichever your codebase already uses with the Declaration option.

Why are dates typed as string?

JSON has no date type, and JSON.parse returns the original text, so a timestamp really is a string at runtime. Convert it yourself where you need it, for example new Date(order.placedAt).

Is my JSON uploaded or saved anywhere?

No. Parsing and type generation run in your browser, nothing is sent over the network, and the JSON text is never written to storage or the URL. Only your option choices are remembered on this device.