How-to guide

How to Generate TypeScript Types from JSON

Paste a representative JSON response into a converter and it infers an interface from the keys and value types. The generated result is a starting point rather than a finished type, because a single sample cannot show which fields are optional, which may be null, and what an empty array contains. Fix those three things by hand.

JSON to TypeScript

Generate TypeScript interfaces from a sample JSON payload.

Open the tool

Type generation from a sample is inference, and inference from one example is guesswork about everything the example did not contain. The output is still worth having — it gets the shape and the nesting right, which is the tedious part.

What it cannot know is variation. If the sample happened to include a middle name, the generator makes it required; if an array happened to be empty, it has nothing to infer an element type from.

Step by step

  1. Pick a response with the fields populated

    Choose a sample where optional fields are present rather than absent. A generator can only describe what it sees, so a minimal response produces a minimal and misleadingly narrow type.

  2. Generate the interfaces

    Nested objects become their own named interfaces, referenced from the parent. Arrays become typed arrays based on the first element. Review the names, which are derived from the keys and are often close but not idiomatic.

  3. Mark the optional fields

    Add ? to any property the API may omit. This is the single most valuable manual edit, because a missing field typed as required is a runtime error that the compiler promised could not happen.

  4. Separate null from optional

    A field that is absent and a field that is present with the value null are different situations. Use name?: string for absent and name: string | null for explicitly null. Conflating them causes checks that pass the compiler and fail at runtime.

  5. Fix the empty arrays and the numbers

    An empty array in the sample generates never[] or any[] and must be typed by hand. Also check whether numeric-looking values are really numbers: an identifier that arrived as "0042" is a string, and typing it as a number loses the leading zeros.

Example

The generated interface, and the same interface after the three manual corrections.

Generated

interface User {
  id: number;
  name: string;
  nickname: string;
  tags: never[];
}

Corrected

interface User {
  id: number;
  name: string;
  nickname?: string | null;
  tags: string[];
}

Frequently asked questions

Can I generate types from a single API response?
Yes, and it is the usual starting point, but one response cannot show which fields are optional or nullable. Generate from a populated example, then widen the type by hand where the API may vary.
Why did my array come out as never[]?
Because it was empty in the sample, so there was no element to infer from. TypeScript uses never[] for an array that provably contains nothing. Replace it with the real element type.
Should optional fields use ? or | null?
They mean different things. ? means the key may be absent; | null means the key is present with a null value. APIs that return explicit nulls need the second, and many need both written as field?: string | null.
Do generated types validate data at runtime?
No. TypeScript types are erased at compile time and enforce nothing once the code is running. If you need to check that a response really matches the shape, use a runtime validator or a JSON Schema alongside the types.
What about numbers that are really identifiers?
Type them as strings. An ID with leading zeros or more than fifteen digits loses information when treated as a number, and JavaScript cannot represent integers above 2^53 exactly.

Tools used in this guide

All tools →
All guides →

Last reviewed .