JSON to TypeScript Converter

Paste a JSON response and get exported TypeScript interfaces you can drop into your code. Inference runs on your machine, so real API payloads are never uploaded.

JSON → TypeScript

Input

Settings

History

Load from URL

Why generate types from a JSON sample

Typing an API response by hand is slow and drifts out of date. Generating the types from a real payload gives you autocomplete and compile-time checks in minutes: paste the body from your network tab, a webhook delivery or a fixture file, and copy the result into a types.ts. It is also a quick way to understand the shape of an unfamiliar API.

How types are inferred

  • Every object becomes an exported interface. Nested objects get their own interface, named after the key: address becomes Address, and items of an orders array become Order.
  • Strings, numbers and booleans map to string, number and boolean. Strings are never narrowed into dates, enums or UUIDs, because a single sample cannot prove that.
  • Arrays become T[]. When the items have different types, you get a union such as Array<number | string>. An empty array is unknown[], since there is nothing to infer from.
  • All objects in an array are merged into one interface. A key present in only some items becomes optional (note?: string); a key that is null in some items becomes a union with null (nick: null | string).
  • A key whose only value is null is typed null; widen it when you know the real type.
  • Keys that are not valid identifiers, such as created-at, are kept as quoted property names, so the interface still matches the JSON exactly.

If the JSON’s root is an array or a plain value, the root type is an alias: export type Root = RootElement[];.

Options

Root type name (default Root) names the top-level type. It is converted to PascalCase, so user profile becomes UserProfile, and a name starting with a digit gets a T prefix.

Declare as chooses between interface (the default) and type alias (export type Address = { ... }). Interfaces can be extended and merged; type aliases are preferred by some style guides and work better when you later combine shapes with & or |. The members are identical either way.

The output is formatted with Prettier.

Numbers, precision and limits

TypeScript has one number type, so integers and decimals both map to it. Integers larger than 2^53 cannot be represented exactly by a JavaScript number; when the sample contains one, a warning suggests switching that field to bigint or string (and parsing it accordingly). See big integers in JSON for strategies.

The generated code contains types only — there is no runtime validation, so data that differs from the sample will not be caught at run time. For validation, generate a schema with JSON to JSON Schema and check payloads against it. A richer sample (several array items, with and without optional keys) yields more accurate optional fields. Duplicate keys in the input are reported as warnings; inference uses the final value.

Examples

User with nested objects

Produces Root, Address and Order interfaces; note is optional because only one order has it.

Input
{
  "id": 1042,
  "name": "Aisha Tan",
  "email": "aisha.tan@example.com",
  "active": true,
  "tags": ["admin", "beta"],
  "address": { "city": "Singapore", "postcode": "018956" },
  "orders": [
    { "id": "ord_1", "total": 129.9, "paid": true },
    { "id": "ord_2", "total": 79, "paid": false, "note": "gift" }
  ]
}
Output
export interface Root {
  id: number;
  name: string;
  email: string;
  active: boolean;
  tags: string[];
  address: Address;
  orders: Order[];
}

export interface Address {
  city: string;
  postcode: string;
}

export interface Order {
  id: string;
  total: number;
  paid: boolean;
  note?: string;
}
Open this example in the tool

Array root as type aliases

The root becomes export type ProductList = ProductListElement[], discount is number | null and bundle is optional.

Input
[
  { "sku": "KB-104", "price": 129.9, "discount": null },
  { "sku": "MS-220", "price": 79, "discount": 0.15, "bundle": ["MS-221"] }
]
Output
export type ProductList = ProductListElement[];

export type ProductListElement = {
  sku: string;
  price: number;
  discount: number | null;
  bundle?: string[];
};
Open this example in the tool

Common errors and how to fix them

ErrorCauseFix
Some integers are larger than 2^53; they are typed as floating-point numbers. Use a 64-bit or big-integer type if you need exact values.
Explained
A warning: the sample contains IDs or amounts beyond JavaScript’s safe integer range.Change those fields to bigint or string and parse them with a big-number-aware JSON parser.
Object keys must be in double quotes: found …
Explained
The input is a JavaScript object literal rather than JSON.Quote the keys, or convert the text with JSON5 to JSON first.
The JSON is nested more than 200 levels deep, too deep to generate types forThe input is extremely deeply nested, often a recursive structure serialised many levels down.Trim the sample to a few levels; the repeated shape will still be inferred.
Unexpected '<' where a value was expected
Explained
An HTML error page was pasted instead of the JSON response body.Check the request in your network tab and copy the actual JSON response.

Frequently asked questions

Should I choose interface or type alias?

Either works for describing JSON. Interfaces are the common default and support declaration merging; type aliases suit codebases that prefer them or combine types with unions and intersections.

How are optional fields detected?

By comparing all objects that end up in the same type. A key missing from at least one of them is marked optional with ?.

Does it recognise dates or enums?

No. ISO date strings stay string and repeated values do not become enums, because one sample is not enough evidence. Refine those fields by hand.

Is my JSON sent to a server to generate types?

No. The inference engine runs inside your browser, so the payload never leaves your machine.

Related tools