Developer tools

JSON to TypeScript types and Zod schema

Writing types by hand from an API response is slow and easy to get wrong. Paste the JSON and the tool infers TypeScript interfaces, or a Zod schema you can use for runtime validation. Objects in arrays are merged, so a field that some records have and others do not is marked optional automatically.

Runs entirely in your browser. Nothing you enter here is uploaded.

How to use it

  1. Paste sample JSON on the left. The more complete the sample the better: several different records in an array let the tool see which fields are optional.
  2. Enter a name for the root type, such as User or OrderResponse.
  3. Choose TypeScript interfaces or a Zod schema. The code appears on the right as you type; copy it or download a .ts file.
  4. Review the result, especially fields whose sample value is null or an empty array, and fill in the real types.

How types are inferred

Basic types and nesting

JSON strings, numbers, true or false and null become string, number, boolean and null. Each nested object gets its own interface named after its key in PascalCase: owner becomes Owner. Array item types use the singular: items gives Item, categories gives Category and boxes gives Box, while words ending in ss or us, such as status, are left alone.

Merging objects in arrays

API arrays often contain records where some have a field and some do not. The tool merges all objects in an array into one interface: fields present in every item are required, and fields present in only some get a question mark after the name, TypeScript's syntax for optional properties. A field with different types in different records becomes a union — qty that is sometimes a number and sometimes null becomes number | null — and a mixed array becomes (number | string)[].

Name clashes and reuse

Objects with exactly the same structure share one interface instead of producing duplicates. If two different structures would get the same name, the second gets a number, such as User and User2; rename them to suit your domain. Keys that are not valid JavaScript identifiers, such as first-name or 2fa, are quoted.

Zod schema

In Zod mode each interface becomes a z.object, optional fields get .optional(), and schemas are defined before they are used. The last line uses z.infer to derive a type with the same name from the schema, so types and runtime validation come from one definition. Install zod in your project to use it.

Examples

With the sample loaded and the root type named User, the result is:

export interface User {
  id: number;
  name: string;
  email: null;
  roles: string[];
  orders: Order[];
}

export interface Order {
  id: number;
  total: number;
  items: Item[];
  coupon?: string;
}

export interface Item {
  sku: string;
  qty: number;
}

Only the second order has a coupon, so coupon is optional. The second order's items array is empty, and merged with the first it is still Item[]. email only appears as null in the sample, so the tool can only infer null; in reality it is probably string | null, which is exactly the kind of thing to check by hand.

Limits

  • Types come from the sample only. Fields or value types that do not appear in it are not in the result.
  • A field that is only ever null is typed null, and a field that is only ever an empty array is typed unknown[]; fill these in yourself.
  • Dates, enums and string formats are not recognised: "2026-09-30" is a string and "admin" does not become a literal type.
  • Integers above 2^53 lose precision in JavaScript and are still typed number; APIs that send large integers as strings will show string in the sample.

Frequently asked questions

How are optional fields detected?

From objects in arrays: a field present in only some of them is optional. Fields of a single object are treated as required.

Why is a field typed null?

Its only value in the sample was null, so nothing else can be inferred. Change it to string | null or whatever it really is.

Interface or Zod schema?

Interfaces for compile-time checking only; a Zod schema when you also want to validate API data at runtime, with z.infer giving you the same type.

Do repeated structures create several interfaces?

No. Identical structures share one interface.

Is my JSON uploaded?

No. Everything is inferred in your browser.

Sources and further reading

↵ to open · Esc to close