Skip to content
epitometool

JSON to TypeScript interfaces

JSON & data

Generate TypeScript interfaces from any JSON payload — paste, copy, ship.

Updated

Options

Input JSON

TypeScript

  • EnterCopy output
  • KClear input

Quick start

How to generate TypeScript interfaces from JSON

Paste any JSON value to get TypeScript interface declarations you can drop straight into your codebase.

  1. Step 1
    Paste JSON

    Drop an API response, a config file or a sample row into the input pane. Multiple records produce more accurate optional flags.

  2. Step 2
    Tune the output

    Choose the root type name, named vs inline interfaces, unknown vs any, and tab vs space indent. Output updates instantly.

  3. Step 3
    Copy

    Click Copy (or ⌘/Ctrl + Enter) to grab the generated TypeScript. Everything runs locally — no upload, no telemetry.

In-depth guide

JSON to TypeScript interfaces — paste, copy, ship

Paste any JSON value — an API response, a config file, a sample row from a database query — and get TypeScript interface declarations you can drop straight into your codebase. Everything runs locally; the inference walks the parsed tree, merges sibling shapes and coalesces duplicates so the output stays compact.

How the type inference works

  1. Parse the JSON via JSON.parse.
  2. Walk the tree and produce a "shape" for each value — primitive, array, object or union.
  3. Merge sibling shapes (array elements, objects with the same key set) into a single canonical shape. Missing keys → optional. Different primitive types → union.
  4. Emit one export interface per distinct object shape, plus a root interface Root or type Root depending on the JSON root type.

This is deterministic — the same JSON input always produces the same TypeScript output, byte-for-byte.

Optional vs required, null vs union

Two related but distinct concepts:

  • Optional (key?:) — the key may be absent from the object. Inferred when the same array contains objects where the key is sometimes present, sometimes not.
  • Nullable (: T | null) — the key is always present, but its value may be null. Inferred when the value is null in one sibling and a concrete type in another.

For an API response, paste an array of several real samples (not just one) — the merger only knows a field is optional if it has multiple samples to compare.

Tips for the best output

  • Paste multiple records when you can. A single sample gives you the right keys but no optional flags.
  • Use meaningful root names. "User", "Order", "ApiResponse" — the inferrer derives child interface names from the parent key, so good names propagate.
  • Watch for numbers that should be strings. JSON has no integer vs decimal distinction; phone numbers, IDs and ZIP codes are often JSON numbers but should be string in TypeScript to preserve leading zeros.
  • Prefer unknown over any for empty arrays — it forces a narrow at the use site, which catches bugs early.

Common pitfalls

  • Validate the output before committing it, especially when fixing almost-valid input.
  • Escaping, comments, trailing commas, and mixed encodings are the usual source of surprising results.
  • For production config, keep a copy of the original until the consuming system accepts the rewritten file.

Privacy and security

Browser-first by design. The tool page explains any exception before you use it.

Pasted code and data are processed locally in the page. EpitomeTool does not send your input to a formatting, validation, or conversion API.

Frequently asked questions

Is my JSON uploaded to a server?

No. Parsing, shape inference and TypeScript code generation all run entirely in your browser. The JSON you paste never leaves your device.

What kind of TypeScript does it produce?

By default, an `export interface` per nested object and an `export interface Root` for the top level. If the JSON root is an array or a primitive, the output is `export type Root = …` instead. You can switch the root name in the options panel.

How are arrays handled?

Element types are inferred by merging the shapes of every item in the array. Heterogeneous arrays produce a union (`string | number`). Arrays of objects with slightly different keys produce a single interface where the missing keys are marked `optional?:`.

What's the difference between unknown and any?

`unknown` is the safer default: TypeScript forces you to narrow it before use. `any` opts out of type checking entirely. We default to `unknown` for empty arrays and shapes we can't infer. Toggle the option if you need `any` for legacy code interop.

What about nullable fields?

When a value is `null` in one sample and a real type in another (across array elements), the field becomes a union like `string | null`. When the same key is present in some array items but missing in others, it becomes optional with `key?:`.

Does it support nested interfaces?

Yes — that's the default. Each nested object gets its own named interface, with names derived from the parent key (singularized for array elements: `users: User[]` produces `interface User`). Identical shapes across the tree are coalesced into a single interface to avoid duplication.

Can it generate types from an API response?

Yes — paste a single representative response. For better optional/required accuracy, paste an array containing several real responses; the merger will mark fields optional that aren't present in every sample.

What's the difference vs quicktype?

Quicktype is an excellent, heavier tool that also handles TypeScript, Go, Rust, Swift and more. This tool is purpose-built for browser-only TypeScript-from-JSON: ~2 KB of code, no WebAssembly, no network, instant output. If you need multi-language output or JSON Schema input, use quicktype.io.

Keep exploring

More tools you'll like

Hand-picked utilities that pair well with the one you're on — all free, client-side, and zero-signup.