The Code Dealer Logo
All tools

JSON to TypeScript Converter

Paste a JSON response and get typed interfaces back, with the inference rules spelled out so you know exactly what the output is claiming.

The Code Dealer
  • typescript
  • tools
  • api

Typing a third-party API by hand is tedious and error-prone: you miss a nested object, guess wrong about which fields are optional, and find out in production. This tool takes a JSON sample and generates the TypeScript interfaces that describe it.

Paste a response body, get types back. Nothing is uploaded — the conversion runs entirely in your browser.

What the output looks like

Given a typical API payload:

{
  "id": "crs_9f2a",
  "title": "Advanced TypeScript",
  "price": 4900,
  "isPublished": true,
  "tags": ["typescript", "advanced"],
  "author": { "id": "usr_11c", "name": "Ada" },
  "archivedAt": null
}

You get:

export interface Author {
  id: string
  name: string
}
 
export interface Course {
  id: string
  title: string
  price: number
  isPublished: boolean
  tags: string[]
  author: Author
  archivedAt: null
}

Nested objects are extracted into their own named interfaces rather than being inlined, so you can import and reuse Author on its own.

The inference rules

Everything the tool does follows from one constraint: JSON carries values, not types. The generator reads a sample and infers the narrowest type that sample is consistent with. Knowing the rules tells you where to check the output.

Primitives

string, number, and boolean map directly. JSON has one numeric type, so integers and floats both become number — there is no way to tell an id: 3 that must stay an integer from a rating: 3 that could be 3.5.

Arrays

The element type is the union of every member's type. An array of objects with matching shapes produces one interface; mismatched shapes produce a union, and that union is usually the signal that you are looking at a discriminated union worth naming yourself.

An empty array cannot be inferred at all and becomes unknown[].

Null

A null value in the sample means the field is nullable, but a sample can only prove nullability — never absence. archivedAt: null above is typed null because that is all the data supports. What you almost certainly want is:

archivedAt: string | null

Paste a second sample where the field is populated, or widen it yourself.

The three things to always fix by hand

  1. Optional versus nullable. A key missing from your sample is not necessarily optional, and a key present in it is not necessarily required. Only the API contract knows. Check the docs and add ? where it belongs.
  2. Dates. ISO timestamps arrive as strings and are typed string. That is correct for the wire format — decide deliberately whether your app types parse them into Date at the boundary or keep them as strings.
  3. String literals. A status: "published" field becomes string. If the API only ever returns three values, narrow it to a union and let the compiler check your switch statements.

When to reach for something stronger

Generated types describe a sample, not a contract — they will drift the moment the API changes and nothing will tell you. For an API you own, generate types from the schema instead: GraphQL codegen from your SDL, or Prisma's generated client types straight from schema.prisma. Those regenerate with the source and stay honest.

Use this tool for the other case — the undocumented endpoint, the webhook payload you captured once, the response you are typing right now so you can keep working.