JSON to TypeScript

Generate TypeScript interfaces (or type aliases, or Zod schemas) from a JSON sample. Handles nested objects, mixed-type arrays, nullable fields, optional fields, and ISO date detection. Runs entirely in your browser. Useful for typing an API response, locking in a config shape, or scaffolding model definitions from a sample payload.

How to use the JSON to TypeScript tool

Paste a JSON sample, name the root type, click Convert. The output panel shows a valid TypeScript file with the inferred types. Copy it into your codebase and you're typed.

For best results, paste a JSON sample that's representative of the data you actually receive — not just the happy path. If a field is sometimes null and sometimes a string, include both in an array sample so the tool unions them correctly. If a field is sometimes absent, include records both with and without the field so optionality is captured.

When the output format is Zod schema, you get parse-able runtime validators. Use them at API boundaries: parse incoming data, get typed values out, throw on mismatch. This is more robust than trusting JSON.parse + a cast.

How the inference works

The tool walks the JSON tree depth-first. For each value it determines a base type (string, number, boolean, null, object, or array). Objects become interfaces named by key path. Arrays of primitives become T[]; arrays of objects become arrays of generated interfaces, with shape merging if the option is on.

Optionality is determined by comparing object shapes across array elements: if a key appears in 8 out of 10 elements, it's marked ?: (optional). Nullability is determined by whether any value at that path is null.

Date detection runs a regex (^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}) against string values. Matches keep string as the type but get a JSDoc comment hinting at the format, because TypeScript has no native Date distinct from string in JSON.

Where this is useful

  • API client scaffolding. You hit a new third-party API, capture the response, paste it, get a starting set of types.
  • Backend payload typing. A webhook delivers JSON; you want to type the parsed body without writing the schema by hand.
  • Config file shape. Your app reads a JSON config; paste the sample to get a type that catches typos at compile time.
  • LLM output structure. When you constrain an LLM to a specific JSON shape, paste an example output to get the type that JSON.parse would yield.
  • Mock data typing. A test fixture is a JSON literal; matching its type to the production type catches drift.

Limits and caveats

Type inference from JSON is structural — it captures what's in the sample, not what's possible. A field that's always "active" in your sample will be typed as the string literal "active", even though the API might return any string. The tool widens single-value primitives to base types (string not "active") unless the "Preserve literal types" option is on (off by default for this reason).

Discriminated unions are not auto-detected. If your API returns objects with a type field that determines the rest of the shape, you'll get a structural union, not a tagged union. Refine the generated types by hand for that pattern.

Numbers are typed as number. JSON does not distinguish integers from floats; if you need bigint for very large IDs, edit the generated type.

Frequently asked questions

How does the tool handle arrays where elements have different shapes?

It unions them. [{"a":1}, {"b":2}] becomes Array<{ a?: number } | { b?: number }> by default. If the "Merge similar shapes" option is on, the tool detects when shapes mostly overlap and produces { a?: number; b?: number } instead, which is what you usually want.

What about nullable fields?

When a value is null in the input, the generated type is null. When a field is present in some array elements but missing in others, the field is marked optional with ?. When a field appears as both null and a value across different inputs, the type becomes T | null.

Does it generate types or interfaces?

Default is interface because they're extendable and play better with IDE tooltips. Switch to type aliases if you prefer or if you need union/intersection composition. Both produce valid TypeScript; pick what matches your codebase style.

Can it generate Zod schemas?

Yes — switch the output format to "Zod schema." Useful if you want runtime validation in addition to static types. The generated schemas use z.object, z.array, z.string, z.number, z.boolean, z.null, z.union. Optional fields use .optional().

How do I name the root interface?

The "Root name" field. Defaults to Root; change it to whatever matches your domain (e.g., ApiResponse, User). Nested object types are auto-named based on the key path (e.g., a user.address object becomes UserAddress).

Does it handle date strings?

Heuristically. ISO 8601 timestamps (2026-05-28T12:34:56Z) are detected and typed as string by default with a comment noting the ISO format. Toggle "Detect date strings" off if you want pure structural inference.