Skip to main content

JSON to TypeScript Interface — Union Detection, Optional Inference, Zero Upload

JSON to TypeScript interface — paste JSON, get clean interfaces with union types from arrays, optional vs required detection, root name customizable.

  • Runs locally
  • Category Developer & DevOps
  • Best for Formatting, validating, shrinking, or inspecting code-adjacent text.
Examples:
How union & optional detection works

Array elements that look different get merged into one interface: keys missing from any sample become optional (?); scalar types pile up into a union (number | string | null). Toggle "Exact" to mark every key required regardless of array sampling — useful when your JSON is a single ground-truth example, not a sampled list.

What this tool does

Paste any JSON payload — a GitHub API response, a Stripe webhook, a GraphQL data block, a config file — and walk away with a clean `.ts` file of `export interface` declarations ready to drop into your project. The inferer reads every object key, merges array elements into a single union'd interface, marks fields as `?` when they are absent from at least one sample in an array, escapes non-identifier keys with quotes, and gives you a root name you actually want to import. Toggle interface vs type alias, readonly vs mutable, unknown vs any for fallbacks, and exact mode (no optionals) for ground-truth payloads. 100% client-side, your JSON never leaves the tab.

Tool details

Input
Text + Numbers + Structured content
The page exposes text boxes, numeric controls, file pickers, or structured inputs depending on the tool.
Output
Live result + Copy + Download
The result area focuses on usable output, with copy, download, or preview actions when supported.
Privacy
Browser-side processing
The main tool logic does not call an external API, so inputs normally stay in the current tab.
Save / share
Shareable URL state
Key settings are encoded in the URL so another person can reopen the same setup.
Performance budget
Initial JS <= 25 KB
No WASM budget is declared, keeping the tool quick to open on mobile.
Best fit
Developer & DevOps · Developer
Category and role tags drive related tools, internal links, and quick fit checks.

How to use

  1. 1. Input

    Paste or drop your content into the tool panel.

  2. 2. Process

    Click the button. All processing is local in your browser.

  3. 3. Copy / Download

    Copy the result or download to disk in one click.

How JSON to TypeScript Interface fits into your work

Use it in the small gaps between coding, reviewing, debugging, and shipping.

Developer jobs

  • Formatting, validating, shrinking, or inspecting code-adjacent text.
  • Preparing snippets for documentation, tickets, commits, or handoff.
  • Checking a small payload quickly without switching tools.

Developer checks

  • Run irreversible transforms like minify or obfuscate on a copy.
  • Keep secrets out of pasted snippets unless the tool explicitly stays local.
  • Use your normal tests or linter before shipping transformed code.

Good next steps

These links move the current task into a more complete workflow.

  1. 1 JSONPath / JMESPath Query Tester JSONPath / JMESPath query tester — paste JSON, write a path, see matched values + matched paths highlighted live. Open
  2. 2 JSON to Go Struct JSON to Go struct — paste JSON, get typed structs with json tags, exported fields, nested sub-structs, pointers for nullable, int64 and omitempty options. Open
  3. 3 JSON Formatter & Validator Format, validate, and minify JSON instantly — right in your browser. Open

Real-world use cases

  • Type a GitHub / Stripe API response without writing types by hand

    You're integrating with the GitHub API for the first time and the docs list 40 fields on the user object. Curl the endpoint once, paste the JSON here, set root name to `GitHubUser`, copy the output into `src/types/github.ts`. The nested `plan` object becomes a `GitHubUserPlan` interface automatically. Now your `fetch('/user').then(r => r.json() as Promise<GitHubUser>)` has real autocomplete — and when GitHub adds a field next year, you re-paste the new response and diff the file.

  • Generate types for a Postgres `row_to_json` query

    You have a SQL query that returns one row per record with nested `row_to_json(addr)` joins. Run it once, copy the JSON column, paste here, set root to `OrderRow`. The address sub-object lifts out as `OrderRowAddress`. Now your `db.query<OrderRow[]>(sql)` returns a typed array with the exact shape your SQL emits — no manual interface that drifts from the query.

  • Build types for a webhook payload you haven't shaped yet

    A vendor (Slack, Linear, Vercel) is sending you an event. Their docs are out of date. Log the first 3 payloads, paste them as a JSON array, the optional-field detection flags everything that isn't always present. The resulting interface tells you not just the shape but which fields you can rely on vs which are situational — way more useful than a doc page that says "this field is sometimes there".

  • Migrate from `any` to `unknown` in a legacy codebase

    Your old code does `const data: any = await res.json()`. Pick a representative response, paste it, generate types, replace the `any` with the new interface. Repeat for every endpoint. You haven't refactored the runtime — you just gave the next dev a map of what the response actually looks like.

  • Document an internal JSON-RPC contract for new hires

    Your team's internal RPC has a `methods.json` spec but the response shapes were never typed. Paste each example, generate `RpcGetUserResponse`, `RpcListOrdersResponse`, etc., commit them to `packages/rpc-types/`. New hires can now Cmd-click any RPC method and see the exact shape — institutional knowledge moved from Slack threads into the type system.

  • Type a GraphQL response without setting up codegen

    You have a one-off GraphQL query you're not running through codegen (small project, prototype, side script). Run it once in the playground, copy the `data` field, paste here, root name `ViewerData`. You get the same `data.viewer.repositories.nodes[0].name` autocomplete that real codegen would give, in 5 seconds, without `.graphqlconfig`.

Common pitfalls

  • Pasting a single object and expecting optional fields. A single object root has no ambiguity — every key is required. Optional inference only kicks in across an array of multiple objects (where some have a key and others don't). If you want everything optional from one object, write the JSON as `[{...}]` instead.

  • Forgetting that JSON numbers all become `number` — there is no `int` vs `float` distinction. A field that is always `42`, `43`, `44` still types as `number`, not as a literal `42 | 43 | 44`. Use a runtime validator (zod, valibot) if you need narrower types.

  • Treating the output as a JSON Schema. It's a TypeScript type only — there is no validator generated. The output tells the compiler what shape to expect; at runtime an API can return any garbage and TS won't notice. Pair with a runtime validator at the network boundary.

  • Pasting a giant JSON (10 MB+) and expecting instant results. The inferer is O(n) but the React re-render isn't free. For huge payloads, sample down to ~100 KB first — the inferred shape is the same.

  • Pasting a JSON5 / JSON-with-comments blob and getting a parse error. We use the strict `JSON.parse` — trailing commas, comments, unquoted keys all fail. Strip those first or use the YAML→JSON converter as a pre-step (YAML is a JSON superset that tolerates comments).

  • Setting root name to something that isn't PascalCase like `user_data`. The tool converts it (`UserData`) but if you wanted to keep snake_case for an exported binding you can't — TS interface names follow PascalCase by community convention, and we enforce it to avoid lint errors downstream.

Privacy

Your JSON never leaves this browser tab. The textarea content is intentionally NOT written to the URL — only your option choices (root name, declaration form, readonly, unknown-as, exact mode) sync via `useUrlState`. That means a "Share settings" link lets a colleague open the tool with the same configuration but their own payload — they don't accidentally inherit yours. Parsing and inference use the browser's built-in `JSON.parse`; there is no network call, no analytics on the textarea content, and nothing stored in localStorage. Safe for production API responses, internal payloads, customer-shaped examples, and pre-publish endpoint specs.

FAQ

Tool combos

Folks in your role tend to reach for these alongside this tool.

Made by Toolora · 100% client-side · Updated 2026-05-29