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.