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.
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. Input
Paste or drop your content into the tool panel.
-
2. Process
Click the button. All processing is local in your browser.
-
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 JSONPath / JMESPath Query Tester JSONPath / JMESPath query tester — paste JSON, write a path, see matched values + matched paths highlighted live. Open
- 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 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.
- Add Line Numbers Number every line of pasted text — set start, step and separator, zero-pad to align, skip blanks, or strip numbers back off — browser-only
- AES Text Encryptor Encrypt & decrypt text with a password — AES-256-GCM + PBKDF2 via WebCrypto — 100% in your browser, nothing uploaded
- Affine Cipher Encoder & Decoder Encrypt and decrypt the ax+b affine cipher with live modular-inverse check, browser-only
- Age Difference Calculator The exact gap between two birthdays — years/months/days, percentage, and the date one person is twice the other's age — browser-only