Skip to content

Generate TypeScript interfaces from JSON

Turn a real API response into named TypeScript interfaces, with optional keys, union types and nested interfaces inferred from the actual data.

  • Runs in your browser
  • Files are never uploaded
  • Free, no account
JSON to TypeScript interfaces
Paste a real API response and get types that match its actual shape: nested objects become named types, keys missing from some array elements become optional, and values that vary become unions.

The name given to the outermost type.

Your JSON never leaves this tab — check it yourself—

Starting the network probe…

The counter above wraps fetch, XMLHttpRequest and navigator.sendBeacon in this tab and counts every call. It does not block anything — it just reports.

Two ways to verify independently

  1. Turn off Wi-Fi or enable airplane mode, then use the tool. It keeps working, because the page is already fully loaded.
  2. Open your browser devtools, switch to the Network tab, clear it, and run the tool. No new row appears.

Why this matters

In 2025 researchers found that popular online formatters had retained tens of thousands of user-submitted snippets — JSONFormatter.org and CodeBeautify together exposed roughly 80,000 saved documents, many containing live cloud credentials, private keys and internal database connection strings, because “format this” quietly meant “upload this”. A separate incident exposed roughly 3.5 million user PDFs on a document-conversion service. The only structural fix is not sending the data in the first place: this site is served under a Content-Security-Policy whose connect-src contains no third-party origin, so a request off this device cannot be made even by accident.

How the inference works

The generator does not guess. It walks the parsed value and builds a shape tree, then merges shapes wherever the same position holds more than one value — every element of an array, and every occurrence of the same nested object.

  1. Scalars map directly: string, number, boolean, null.
  2. Objects merge field by field. A field present in every merged sample is required; a field present in some is marked ?.
  3. Arrays merge their elements into a single element type. If the merged type has more than one possibility it becomes a union.
  4. Identical shapes collapse to one interface, so a document with author objects in three places produces one Author.
  5. Names come from the key holding the object, converted to PascalCase and singularised for array elements: line_items gives LineItem.

Paste more than one record

This is the single highest-leverage thing you can do. From one record the generator can only conclude that every field is required and every type is exactly what it saw. From ten records it can see that gift_wrap appears on two of them and mark it optional, that discount_code is sometimes a string and sometimes null, and that quantity is always an integer.

Wrap several responses in an array and paste that. The generated root will be an array type, and the element interface will be the merged, accurate one.

What generated types cannot tell you

RealityWhat the generator seesWhat to do
A field is nullable in production but was populated in your samplestringCheck the API docs and widen to string | null
A field is one of four fixed valuesstringReplace with a union of literals
An ISO datestringKeep as string, or use a branded type
A 19-digit ID sent as a numbernumberAsk for it as a string — JavaScript cannot hold it exactly
An empty arrayunknown[]Get a sample with elements in it
A map keyed by IDOne field per key in the sampleReplace with Record<string, T>

That last row is worth watching for. An object used as a dictionary — keys are user IDs, values are user objects — generates one optional field per ID in your sample, which is not what you want. Recognise it by an interface with a dozen numeric-looking field names.

Interface or type alias?

Both are switchable here. interface supports declaration merging and produces slightly friendlier error messages when a mismatch is deep; type can express unions, intersections and mapped types that an interface cannot. For plain object shapes generated from JSON the two are interchangeable, so pick whichever your codebase already uses and stay consistent.

Runtime validation is the missing half

A TypeScript interface is erased at compile time. Casting a fetch response with as User tells the compiler what you believe and checks nothing at runtime, so the day the API changes you get undefined is not an object three functions away from the cause. If the response crosses a network boundary, generate a Zod schema instead and let z.infer give you the type — you get the same static safety plus a check at the boundary.

Pasting a real response is the point

Good types come from real data, and real data has customer names, email addresses, internal IDs and sometimes a token in it. The inference and the emitters here are plain JavaScript running in your tab: there is no upload step, and the panel under the tool counts the page’s network requests so you can confirm it.

Questions

How does it decide what is optional?

By comparing every element of an array. A key present in all elements is required; a key present in some is marked with `?`. That is why pasting several records gives much better types than pasting one — one record cannot tell the generator anything about variability.

Where do the interface names come from?

From the key that holds the object, converted to PascalCase, and singularised for array elements — so `line_items` produces a `LineItem` interface. Structurally identical objects share one interface, and a name collision gets a numeric suffix.

Why is a field typed `unknown[]`?

Because the array was empty in your sample, so there is nothing to infer an element type from. Paste a response that includes at least one element, or fill it in by hand.

Can I trust the generated types?

Treat them as a first draft. They describe the sample you pasted, not the contract the API promises: a field that happens to be non-null in your response may be nullable in production, and an enum-like string becomes plain `string`. Check them against the API documentation before committing.

Is my API response uploaded anywhere?

No. The inference and the emitter are about 500 lines of JavaScript running in this tab. That matters here more than on most pages — a real API response usually contains customer records, internal IDs and sometimes a token.