JSON Viewer

How to turn JSON into a TypeScript interface

Get types from a real API answer in seconds, and know what the generated types cannot tell you.

Updated 2026-11-04 · 6 minute read

You have an API answer and no types for it. Writing the interface by hand is slow and you will get a key wrong. A tool can read the answer and write the types for you in a second.

This page shows how, and — more useful — says what the generated types get wrong, so you know what to fix by hand.

The quick way

Open the answer in the viewer and choose Tools → To a TypeScript interface. For this input:

{
  "id": 42,
  "name": "Ada",
  "active": true,
  "tags": ["admin", "staff"],
  "profile": { "city": "London", "zip": "N1" },
  "deleted": null
}

you get:

export interface Profile {
  city: string
  zip: string
}

export interface Root {
  id: number
  name: string
  active: boolean
  tags: string[]
  profile: Profile
  deleted: null
}

Each nested object becomes its own interface, named from the key it sits under. A list of objects gives the item type a singular name, so users produces a User interface.

Optional keys

If the answer is a list, the tool reads every record and marks a key optional when some records do not have it:

{"items": [{"id": 1, "note": "x"}, {"id": 2}]}
export interface Item {
  id: number
  note?: string
}

This is the main reason to generate the types from real data and not from one example record. One record cannot tell you which keys are optional.

What the types cannot tell you

A generated type describes the sample you gave it, not the API. These are the four things to fix by hand.

1. null means "unknown", not "always null"

deleted: null

That is almost never right. The field is probably string | null or Date | null, and your sample happened to have no value. Look at every null in the output and decide what the other case is.

2. An empty list tells you nothing

{"tags": []}

gives tags: unknown[]. Find a record that has tags, or write the type yourself.

3. Text is sometimes more than text

status: string
date: string

The API probably allows only "active" | "suspended" | "closed". A union type catches a mistake that string lets through:

status: 'active' | 'suspended' | 'closed'
date: string   // ISO 8601, for example 2026-11-04T09:30:00Z

4. A number may not survive as a number

If an identifier has more than 15 digits, TypeScript's number cannot hold it exactly, and JSON.parse has already changed it before your code runs. Type it as string and make the server send it as text. See big numbers in JSON.

Validate, do not only type

This is the point most people miss.

const user = await res.json() as User

That cast tells the compiler to trust you. It checks nothing at run time. If the API changes, your program carries wrong data until it fails somewhere far away from the cause.

A schema library checks the shape when the data arrives:

import { z } from 'zod'

const User = z.object({
  id: z.number(),
  name: z.string(),
  active: z.boolean(),
  tags: z.array(z.string()),
  profile: z.object({ city: z.string(), zip: z.string() }),
  deleted: z.string().nullable(),
})

type User = z.infer<typeof User>

const user = User.parse(await res.json())   // fails here, with a clear message

The type comes from the schema, so there is one description, not two that drift apart.

If you prefer JSON Schema, write the schema and check the answer against it. This viewer has a Schema action that does exactly that, so you can test the schema against a real answer before you put it in your code. See JSON Schema.

Other ways to get types

Way Good for
This viewer One answer, right now, with no upload
quicktype A whole folder of samples, many languages
OpenAPI generator An API that publishes a specification
zod and friends Types and a check at run time

If the API publishes an OpenAPI document, use it. Types generated from the specification describe what the API promises. Types generated from one answer describe what it happened to send that day.

A good routine

  1. Fetch a real answer and save it.
  2. Generate the types from it.
  3. Read the output and fix the four things above.
  4. Turn the fixed type into a run-time schema.
  5. Keep the saved answer in your tests, and compare it with a fresh one when the API changes.

Try it on your own file. The tool runs in your browser. Nothing is uploaded, and nothing is stored on a server.

Open the JSON Viewer

Read next

JSON Schema — check your data before it breaks something

Write a schema that catches bad data, with the keywords that matter and the traps that waste a day.

Why big numbers break in JSON, and what to do

An identifier of 19 digits goes into a parser and comes out changed. Here is why, and the three ways to stop it.