Free tool

JSON to TypeScript converter

Paste any JSON payload and this free JSON to TypeScript converter generates clean, named interfaces (or type aliases) in your browser — nested objects become their own sub-interfaces, arrays are unioned automatically, and fields missing from some array elements are marked optional. No upload, no dependencies, no account.

JSON to TypeScript converter

Paste a JSON payload and get clean, named TypeScript interfaces back instantly — nested objects, arrays, and optional fields all inferred automatically.

FreeNo upload — 100% privateNo dependencies

Declaration

0 B

0 B

Everything runs locally in this browser tab with a hand-rolled type inference pass over the parsed JSON — no third-party library, no upload. Your data is never sent to a server, so this works offline and stays completely private — safe for API responses, config files, and other sensitive payloads.

How to convert JSON to TypeScript

  1. Add your JSON. Paste it into the input box, click Upload .json to load a file from disk, or click Load sample to try the tool with a ready-made example first.
  2. Set a root type name. By default the top-level type is called Root — rename it to something meaningful for your codebase, like User, ApiResponse, or WebhookPayload.
  3. Choose interface or type. Use the Declaration toggle to switch the generated syntax between interface and type — whichever your project's style guide prefers.
  4. Tune semicolons and the export keyword. Turn semicolons off if your formatter strips them, or turn off export if you're pasting the result straight into a file that already has its own export statements.
  5. Click Generate TypeScript. The output pane fills with your interfaces — copy it with one click or download it as a ready-to-use .ts file.

Because generation happens instantly and entirely client-side, you can tweak the root name or toggle options and regenerate as many times as you like with no rate limit and no waiting on a server.

Why generate TypeScript types from JSON?

Almost every frontend and backend TypeScript project eventually needs to describe the shape of some JSON — an API response, a webhook payload, a config file, a database record, or a fixture used in tests. Writing that shape out by hand is slow and error-prone: it's easy to miss a nested field, mistype a key, or forget that a property is sometimes absent. A JSON to TS generator removes that manual step entirely. You paste the real data, and it reads the actual keys, values, and nesting to produce a type definition that matches exactly what you have — not what you remember the API returning.

This matters more than it looks. TypeScript's whole value proposition is catching mistakes before runtime — autocomplete on API fields, a compiler error when you typo a property name, a red squiggle when you forget to handle null. None of that works if your interfaces are stale, incomplete, or simply absent because writing them by hand felt like a chore. Generating types straight from a real JSON sample keeps your types honest: they describe the data you actually received, not a guess.

It's also a fast way to onboard onto an unfamiliar API. Instead of reading pages of documentation (or worse, no documentation), you can hit the endpoint, copy the response body, paste it in, and have a typed contract in seconds — ready to import into a fetch wrapper, a React component's props, or a Zod-style runtime validator you write afterward.

There's also a maintenance angle. APIs change — a field gets renamed, a new optional property gets added, a value that was always a number starts arriving as a string from a new backend service. When that happens, the fastest way to update your types isn't to hunt through an old interface trying to remember what changed — it's to grab a fresh sample of the current response and regenerate. Treating type generation as a repeatable step, rather than a one-time hand-written artifact, makes it far cheaper to keep your types accurate as the underlying API evolves.

Interface vs type: which should you generate?

TypeScript gives you two ways to describe an object shape: interface and type. For a JSON-derived shape, both work — the choice mostly comes down to convention and a few practical differences worth knowing about.

Aspectinterfacetype
Declaration mergingYes — multiple declarations with the same name merge into one.No — redeclaring a type alias is a compiler error.
Extendingextends keyword, slightly clearer error messages for deep hierarchies.Intersections (A & B) — more flexible, works with unions too.
UnionsNot directly supported.Native — a type alias can be a union of other types.
Common usePublic API shapes, class contracts, anything meant to be extended.Unions, tuples, mapped types, and one-off object shapes.

For most JSON-derived types, either is fine — this tool lets you flip between them with one click so you can match whatever convention your codebase already uses. If your team's ESLint config enforces one or the other (a common rule is consistent-type-definitions), switch the toggle and copy the matching output.

A common rule of thumb: reach for interface when a shape represents an entity that other parts of the codebase might want to extend or implement — a User or Product model, for instance. Reach for type when you need a union (“this field is one of these three literal strings”), a tuple, or a shape you're only ever going to use once and don't expect to grow. Since JSON-derived shapes are frequently just data — records coming back from an API, not classes meant to be subclassed — type is a perfectly reasonable default, and many modern TypeScript style guides (including the popular ones bundled with Deno and several enterprise codebases) now prefer it for exactly that reason.

How optional field detection works

Real-world JSON is rarely perfectly uniform. An API might return a discount field only on orders that have one, or a public flag only on records where it's relevant. If you paste a single JSON object, this tool has only one example to learn from, so every key it sees is treated as required. But if you paste an array of objects — the shape you get from almost any list endpoint — the generator compares every element in the array and works out which keys are shared and which only show up sometimes.

Concretely: the tool collects the full set of keys across every object in the array, then for each key checks whether it was present on every element. If a key is missing from even one element, it's marked optional with a trailing ? — for example discount?: number instead of discount: number. If the same key holds different value types across elements (say, id is sometimes a number and sometimes a string), the generated type becomes a union: id: number | string. This gives you an honest, defensive type instead of one that silently assumes every record looks like the first one in your sample.

This is one of the best reasons to paste an array with a few varied examples rather than a single object, especially for anything sourced from a real API — the more representative your sample, the more accurate the optionality detection.

How the type inference works

Under the hood, this converter walks the parsed JSON value recursively and applies a small set of rules to decide what TypeScript type each piece of data should become:

  • Primitives. JSON strings, numbers, and booleans map directly to string, number, and boolean. null becomes the literal type null.
  • Arrays. An array's element types are inferred and combined into a union if they differ — [1, "two"] becomes (string | number)[]. An empty array has nothing to infer from, so it becomes unknown[] — you'll want to replace that with a real element type once you know what the array is supposed to hold.
  • Nested objects. Every object gets its own named interface (or type), generated from the property key that contains it — an address field produces an Address interface, a shipping_info field produces ShippingInfo. This keeps the output readable instead of collapsing everything into one giant inline type.
  • Repeated shapes are deduplicated. If two different keys (or two array elements) produce objects with the exact same structure — same keys, same types, same optionality — the generator reuses a single interface instead of emitting near-identical duplicates like Address and Address2. This is done by computing a structural signature for each object shape and caching the first name it was assigned.
  • Invalid identifiers get quoted. A JSON key that isn't a valid TypeScript identifier — one with a space, a dash, or a leading digit, like "user-id" or "2fa-enabled" — is kept as a quoted string key, e.g. "user-id": string, exactly as TypeScript requires.
  • Root shape. If your JSON is a single object, the root type name you choose becomes that object's interface directly. If it's an array, the root becomes a type alias pointing at an array of the inferred item type, e.g. type Root = RootItem[].

Limits and things to double-check

No JSON-to-TypeScript generator can read your intent — only your data — so a few things are worth checking by hand after generating:

  • Empty arrays produce unknown[]. There's no element to infer a type from, so you'll need to fill in the real element type once you know it.
  • Number vs. integer isn't distinguished. TypeScript has no separate integer type, so 1 and 1.5 both become number — that's a TypeScript limitation, not a bug in the generator.
  • Dates arrive as strings. JSON has no native date type, so an ISO timestamp like "2026-07-15T10:00:00Z" is typed as string, not Date. Convert it after parsing if you need real Date objects.
  • A single sample can under- or over-fit. If you only paste one example, every field looks required — paste an array with a few varied records for better optional-field detection.
  • Generated types describe shape, not validation. TypeScript types are erased at compile time and don't check anything at runtime. For real runtime validation of untrusted JSON (webhooks, user uploads), pair the generated type with a schema library like Zod or Yup.
  • Very large or deeply nested payloads can produce a lot of generated interfaces. That's expected — split them into smaller, more specific types by hand afterward if the output feels unwieldy.

Common ways to use generated types

  • Typing a fetch response. Paste a sample API response, generate the interface, then use it as the generic on your fetch wrapper: fetch<User>("/api/user").
  • React component props. Convert a JSON fixture into an interface and use it directly as a component's prop type, so your editor autocompletes every field.
  • Config and environment files. Turn a config.json into a typed shape so typos in config keys get caught at compile time instead of at runtime.
  • Test fixtures and mocks. Generate a type once from a real payload, then reuse it to keep every mock and fixture in a test suite consistent with the real shape.
  • Webhook payloads. Stripe, GitHub, and most SaaS webhooks send JSON — paste a sample delivery and get a typed handler signature in seconds.

Already have the JSON formatted the way you want and just need to reshape it first? Run it through the JSON formatter to beautify or validate it before generating types.

Who uses a JSON to TypeScript converter?

  • Frontend developers typing the response from a REST or GraphQL endpoint before wiring it into a React, Vue, or Svelte component, so the editor catches a typo'd field before it ships.
  • Backend developers sharing a typed contract for a new endpoint with the team that consumes it, without hand-writing a separate interface file from scratch.
  • Full-stack engineers keeping request and response types in sync across a Node.js API and its TypeScript frontend, especially on projects that don't yet have a shared schema layer.
  • QA and test engineers converting a captured payload into a type so test fixtures and mocks can't silently drift from what the real API returns.
  • Developers integrating a third-party API — Stripe, GitHub, Shopify, a weather service — who want a typed starting point without waiting for official TypeScript definitions to be published.
  • Students and bootcamp learners exploring how TypeScript's structural type system maps onto real JSON, using the generated output as a worked example.

Frequently asked questions

Does this tool send my JSON to a server?
No. Parsing and type generation both run locally in your browser tab using the built-in JSON.parse and a hand-written inference pass — your data is never uploaded, so it works offline and stays completely private.
How does it decide a field is optional?
Optionality is only detected when you paste an array of objects. The tool merges the keys across every element, and any key that's missing from at least one element gets marked optional (key?: type) in the generated interface.
What happens with deeply nested objects?
Each nested object gets its own named interface, generated from the property key that contains it (e.g. a 'billing_address' field produces a BillingAddress interface), so the output stays readable instead of one giant inline type.
Can I choose between interface and type?
Yes. Use the Declaration toggle to switch between TypeScript interface and type syntax at any time — the tool regenerates the output instantly with your current JSON and root name.
What if two nested objects have the exact same shape?
The generator computes a structural signature for every object it encounters and reuses the first interface it generated for that shape, so identical structures don't produce duplicate near-identical interfaces.
Does it handle invalid JSON gracefully?
Yes. If the input can't be parsed, the tool shows a red error banner with the approximate line and column of the problem, translated from the browser's native JSON.parse error position — the same approach used in the JSON formatter tool.

Generate the types, then ship the link

fewly turns any URL into a short, branded, trackable link — free to start, no credit card.