JSON to TypeScript Converter

Paste a JSON sample and get TypeScript types for it: interface, type, class or a Zod schema. Nested objects get their own named types, optional fields are detected across array items, and null becomes a union. It runs in your browser.


        

How to convert JSON to TS

  1. Paste a real payload. Copy a response from the browser's Network tab, Postman or curl. JavaScript object literals also work (unquoted keys, single quotes, trailing commas), because the input is repaired before inference.
  2. Name the root. Set Root name to the domain concept, such as User or OrderResponse. Nested types are named from their keys, so the whole set reads well.
  3. Pick the output. Choose interface or type for plain type checking, class if your code creates instances, and Zod if you also want to validate data at runtime.
  4. Review and copy. Check every ? and | null against your API docs, then copy the result or download it as a .ts file.

How the types are inferred

JSON carries no schema, so the converter works it out from the values it sees. These are the rules:

JSON sampleGenerated TypeScriptRule
"id": 7id: number;Strings, numbers and booleans map directly. Integers and decimals are both number.
"owner": {"name": "Ada"}owner: Owner; and interface OwnerEach nested object becomes a named type in PascalCase. Identical shapes are reused, and a clash gets a suffix (Owner2).
"items": [{"sku": "A"}]items: Item[];Array item types are named from the singular of the key: items → Item, categories → Category.
[{"a": 1, "b": 2}, {"a": 3}]a: number; b?: number;A key missing from some array items becomes optional.
"note": null in one item, "x" in anothernote: string | null;Observed nulls are added to the union. Turn on null → optional to get note?: string | null.
[1, "two", true](number | string | boolean)[]Mixed primitive arrays become a union.
[]unknown[]There is nothing to infer from. Replace it with the real item type.
"my-key": 1"my-key": number;Keys that are not valid identifiers are quoted.

Example: optional detection across array items

[
  { "sku": "A-1", "color": "red", "surcharge": 0 },
  { "sku": "A-2", "color": "blue" }
]

// generated
export interface Root {
  sku: string;
  color: string;
  surcharge?: number;   // present in item 0, missing in item 1
}

interface vs type vs class vs Zod

OutputLooks likeChoose it when
interfaceexport interface User { id: number; }The default for object shapes. It can be extended and merged, and gives clear error messages.
type aliasexport type User = { id: number; };Your codebase uses type everywhere, or you will combine shapes with unions and intersections.
classexport class User { id!: number; }You create instances, use decorators (TypeORM, class-validator, NestJS DTOs) or want a JSON-to-TS “POJO” model. Required fields use ! so the class compiles under strict.
Zod schemaexport const UserSchema = z.object({ id: z.number() });Data comes from outside your code, such as APIs, forms or files. UserSchema.parse(data) validates the data at runtime, and z.infer gives you the static type, so the two stay in step.

An interface disappears at compile time. It does not check the object your fetch call returns. If a wrong type from the server would be a real problem, generate the Zod version and parse data where it enters your app:

import { z } from "zod";
const res = await fetch("/api/user/7");
const user = UserSchema.parse(await res.json());   // throws if the shape is wrong
type User = z.infer<typeof UserSchema>;

JSON to TypeScript POJO and class generator

If you want model classes rather than type-only interfaces — a “POJO” (plain old JavaScript object) model, a DTO for a NestJS controller, or an entity you will decorate for TypeORM — set Output to class. Every object in the sample becomes an exported class, nested objects get their own classes named from their keys, arrays become typed arrays, keys that are not valid identifiers are quoted, and fields missing from some array items are marked optional with ?.

{"id": 1, "tags": ["a"], "owner": {"name": "Ada"}}

// generated with Output: class
export class Root {
  id!: number;
  tags!: string[];
  owner!: Owner;
}

export class Owner {
  name!: string;
}

The ! is TypeScript’s definite-assignment assertion: it tells tsc --strict the field will be filled (for example by Object.assign(new Root(), json) or class-transformer’s plainToInstance) so the class compiles without a constructor. A value that is only ever null in the sample is typed null; widen it by hand (for example to string | null) once you know the real type. Need POJO classes for another language instead? Use the JSON to Java converter.

Getting accurate types from a sample

Other ways to generate types

# quicktype: several samples, many languages, JSON Schema input
npx quicktype -l ts -s json -o types.ts sample1.json sample2.json

# from an OpenAPI spec instead of a sample
npx openapi-typescript openapi.yaml -o api-types.ts

If your API has an OpenAPI or JSON Schema definition, generating types from that is more reliable than inferring them from a sample. Use this converter when all you have is real data.

Frequently asked questions

How do I convert JSON to TS?

Paste a JSON object or array into the input box and the TypeScript types appear on the right as you type. Choose interface, type, class or Zod, set the root name, then copy the result or download it as a .ts file.

Why is a field marked optional?

A field gets ? only when the input is an array of objects and the field is present in some items but missing from others. A single object never produces optional fields unless you turn on null → optional, which also marks fields that were null.

Should I use interface or type in TypeScript?

For plain object shapes they are equivalent. Interfaces can be extended and declaration-merged and are the usual default. Type aliases are needed for unions and mapped types. Pick one style for your codebase, and the generator follows it for every nested type.

Can it generate a TypeScript POJO or class from JSON?

Yes. Choose class as the output to get a plain TypeScript class, a POJO-style model, for the root object and one for every nested object. Required fields use the definite-assignment ! so the classes compile under strict mode, optional fields get ?, and you can add decorators from class-validator, TypeORM or NestJS on top.

Can it generate a Zod schema from JSON?

Yes. Choose Zod schema as the output. You get one z.object schema per nested shape, with .optional() and .nullable() where the sample needs them, and an exported type for each through z.infer.

How are arrays with mixed types handled?

Objects in an array are merged into one type, and keys missing from some items become optional. Mixed primitives become a union such as (string | number)[], and an empty array becomes unknown[] because there is no item to inspect.

Can I paste a JavaScript object instead of JSON?

Yes. Unquoted keys, single quotes, trailing commas and comments are repaired before the types are inferred, so you can paste an object literal from your code or a console.log output.

Is my JSON sent to a server?

No. Parsing and type generation run in JavaScript in your browser, so you can safely paste internal API responses.