JSON to TypeScript Interface
Derive TypeScript interfaces from a JSON sample. Transcribing them by hand always drops a field or two, and that mistake only surfaces at runtime. Objects inside an array are merged when their shapes differ, and any field missing from some of them is marked optional.
What you enter never leaves your device. Everything runs in your browser; nothing is sent or stored anywhere.
This infers from a single sample. A field that happened to be null shows up as null, and optional fields absent from the sample are missed entirely. Objects inside an array are merged, with ? on anything present in only some of them. Give the output a read before you trust it.
Where the names come from
The root name field becomes the first interface. Nested objects are named after their key in PascalCase — owner becomes Owner, shipping_address becomes ShippingAddress. If two different shapes would get the same name, a number is appended, as in Owner2; if the shapes are identical, one interface is emitted and shared. When the root is an array rather than an object, a RootList alias is added.
How types are inferred
Numbers are number whether integer or decimal. Dates and URLs are just string, because JSON has no notation that distinguishes them. A position that holds several types becomes a union such as string | null. An empty array gives no clue about its contents, so it becomes unknown[]. Keys that are not valid identifiers (content-type, 1st) are quoted.
Merging several samples
A single response yields only the fields that response contained. Wrap several responses in square brackets and paste them as an array, and the inner objects are merged — a field present in only some of them gets ?, and a field that was null in one and a value in another becomes string | null.
Frequently asked questions
Can I use the output as-is?
Read it over first. Inferring from one sample has clear limits: a field that happened to be null looks like it can only be null, and an optional field that was absent from the sample does not appear at all. Pasting several responses together improves the result.
What if the same shape appears more than once?
One interface is emitted and shared. This keeps you from accumulating several identical types under different names.
What happens to `null`?
If the sample contains only null, there is no way to know the real type, so null is what you get. Include a sample with a value, or fix it by hand.
What about nested objects?
Each nested object gets its own interface, referenced from the outer one. Objects inside an array are merged into a single shape, and fields present in only some of them get a question mark.
Can I get `type` aliases instead of interfaces?
No, interfaces only. They are plain field lists, so rewriting them as type means the same thing — if your team standard is type, swap the keyword.
What about objects with numeric keys (maps)?
The keys are used as fields as they are: {"1": …, "2": …} becomes two fields named "1" and "2". If it is really a dictionary keyed by value, change it to Record<string, T> by hand.
Does anything I paste get sent to a server?
No. Everything runs inside your browser and nothing is uploaded or stored. That is why you can use it on things you would not normally paste into a web page, like an internal config file or a production query. It also works with your network disconnected.