100% local — your data never leaves your browser

JSON to TypeScript — Stop Typing Interfaces

Turn a JSON sample into TypeScript interfaces. Nested objects get their own named types, so a payload becomes a file you paste and compile.

Instant Private Zero cookies
Style

JSON input

TypeScript output

What this tool does

A JSON sample becomes TypeScript types, one named interface per object.

{ "id": 1, "name": "Ada", "address": { "city": "Paris" } }
export interface Root {
  id: number;
  name: string;
  address: Address;
}

export interface Address {
  city: string;
}

interface or type, exported or not, and the root name are yours to set.

A list at the root now has a name

An array of objects is the most common sample there is — it is what a list endpoint returns. The output used to be the item interface alone:

export interface UsersItem {
  id: number;
}

and the root name you had typed went nowhere. The list itself is now named:

export type Users = UsersItem[];

export interface UsersItem {
  id: number;
}

This was a defect, found while writing this page and fixed. The Zod and io-ts generators on this site already emitted their root; TypeScript did not.

Same name, different shape

Type names are derived from keys, so two branches can both want Address. When the shapes differ, the second becomes Address2 rather than being merged into a type that fits neither. When the shapes are identical, one definition is shared — a single Address referenced twice.

What one sample cannot say

Nothing is marked optional, and that is deliberate: a key that appears once tells you it can appear, not that it always does. "nickname": null gives you nickname: null, because that is all the sample holds — widen it to string | null yourself once you know.

A twenty-digit identifier is typed number, and a JavaScript number cannot hold it: past 2^53 the value changes when it is parsed. The type is not lying about the sample, it is inheriting a limit of the language — if the field is a snowflake ID, make it string and keep it out of JSON.parse.

A repeated key is refused

{"a": 1, "a": "x"} used to yield a: string, the last occurrence winning in silence. Two values, one key, no way to tell which type the field has: the conversion now stops and says the document is ambiguous. That is the same answer the JSON validator here already gave for the same document.

Private by design

Everything runs locally in your browser with JavaScript. Your data is never uploaded, which makes the tool safe for sensitive content, and it keeps working offline.

Frequently asked questions

Why is no field optional?
Because one document cannot tell you that. A key that is present says the key can be present; it says nothing about whether it is always there. Marking everything required is at least a claim you can check against a second sample — inventing `?` would be a claim about data you never showed the tool.
My list of users only produced `UsersItem`. Where is the list type?
It is there now. An array at the root used to yield the item interface alone, leaving you to write `UsersItem[]` by hand and quietly ignoring the root name you asked for. The output now opens with `export type Users = UsersItem[];`. That was a real defect, found while writing this page.
Two different objects are both called `Address`. What happens?
The second becomes `Address2`. Names come from keys, and two keys in different branches can carry the same name while holding different shapes. Merging them would produce a type that is wrong for both; suffixing keeps each one honest, and identical shapes still share a single definition.

Related converters