Skip to content

JSON to TypeScript

Infers TypeScript interfaces or types from a JSON sample, merging optional and union fields.

Paste a JSON response and get TypeScript interfaces for it. The inference merges every record in the sample rather than reading the first one, so a field that only appears in some of them comes out optional instead of required — which is the difference between a type that compiles and a type that is true.

🔒 Runs entirely in your browsertypescriptjsoncodegentypes
Emit

Sample JSON

Drop a .json file

Read in this tab. Nothing is uploaded.

Give it every element you have. Every extra record narrows the guess — a field missing from one of them is what makes it optional.

TypeScript

How to use it

  1. Paste as many records as you have

    Every element of every array is read and merged, not just the first. Three records tell it far more than one, because a field missing from one of them is exactly what makes that field optional.

  2. Name the root type

    Nested objects are named after the key that holds them, singularised for arrays, so `users` yields a `User`. Only the root needs a name from you.

  3. Read the counts under the output

    Types, optional fields, unions and how many records were merged. A union count above zero means a field held two different kinds of value across your sample — worth looking at before you paste the result into a codebase.

  4. Copy the interfaces out

    The output is a set of exported interfaces in declaration order, ready to paste into a `.d.ts` or next to the fetch that returns them.

Common questions

Is this a validator?

No. TypeScript types are erased at build time, so nothing here checks the response at runtime — a server that changes its shape will hand you a value that lies about its type. If you need the check to happen, emit Zod from the same screen and parse with it.

Why is a field typed `string` when it is a date?

Because in JSON it is a string. The inference is structural — it reports what the values are, and does not guess that an ISO-8601-looking string should become a `Date`. Narrowing that is a decision about your codebase, not about the sample.

What if a field is sometimes a string and sometimes a number?

It becomes a union, `string | number`, and the union count at the bottom goes up. That is usually a signal about the API rather than about the type — a field that changes kind is a bug waiting somewhere downstream.

Are literal types produced from the sample?

No — a `status` that is always `"active"` in three records still comes out as `string`. Three records are not evidence of an enum, and a literal type inferred from too little data is the kind of thing that breaks a build a week later.

Feed it from

Next

These accept what this tool produces, so the result can go straight in.