JSON to TypeScript

Paste a JSON sample and the tool infers TypeScript interfaces that match its shape. Fields are typed by observed values (string, number, boolean, Array<T>), nested objects get their own named interfaces, and fields observed as null or missing become optional (?) or nullable (| null) depending on the style you prefer.

How to convert JSON to TypeScript

  1. 1

    Paste JSON

    A single sample is enough; multiple samples improve nullability and union inference.

  2. 2

    Pick output style

    `interface` (default), `type` alias, or readonly interface with all fields marked `readonly`.

  3. 3

    Pick optional strategy

    Mark fields `?` (may be absent) or `| null` (always present, may be null).

  4. 4

    Copy the types

    Drop into a `.ts` file and you have strongly typed access to the API response.

Example

Input:

{ "id": 1, "name": "Alice", "age": null, "tags": ["admin", "user"], "address": { "city": "Madrid" } }

Output:

interface User {
  id: number;
  name: string;
  age: number | null;
  tags: string[];
  address: Address;
}

interface Address {
  city: string;
}

Type mapping

JSON TypeScript
string string
integer / decimal number
boolean boolean
null alone null
null + T T | null (or T?)
array of T T[]
mixed array (T1 | T2)[]
object Named nested interface
empty array unknown[] (cannot infer)

Optional vs nullable

  • foo?: string, the field may be absent from the object. undefined-checking applies.
  • foo: string | null, the field is always present but may explicitly be null.
  • foo?: string | null, could be absent OR null.

JSON itself does not have undefined, but APIs vary on how they signal absence. Match your API semantics:

  • REST APIs typically omit missing fields -> ?:.
  • GraphQL always returns every requested field -> | null.
  • Some SDKs use both in different contexts.

Union vs literal types

If the tool sees the same string field with a small set of values across samples ("status": "pending", "active", "archived"), it can emit a string literal union:

status: "pending" | "active" | "archived";

Toggle “infer string literal unions” if you want this.

Common mistakes

  • Inferring from one sample. Every field becomes required; nullability cannot be observed. Pass 5-10 varied samples for better types.
  • Empty arrays. "tags": [] gives no type info, the generator emits unknown[]. Provide a sample with at least one element.
  • Mixed-type arrays. [1, "two", true] produces (number | string | boolean)[]. Usually this means the JSON should be redesigned rather than typed.
  • Numeric string keys. JSON {"1": "a", "2": "b"} is still an object in TypeScript (Record<string, string>), not an array. The generator handles this correctly.

Frequently Asked Questions

Match your API. REST APIs that drop null fields want ?:. GraphQL, which always returns every selected field, wants | null. When in doubt, T | null with required syntax is stricter and catches more bugs at compile time.

Yes, if you enable it and provide multiple samples. A field observed with 2-5 distinct string values across samples is emitted as a literal union. Beyond that threshold it falls back to string.

interface for most cases, it’s open to extension and TypeScript optimizes it better. type aliases are useful for unions, intersections, tuples, and mapped types. For JSON-derived types, either works; pick a project convention.

Yes. Each nested object becomes its own interface, with names derived from the key (user.address -> Address). For very deep or repetitive structures, consider a JSON Schema and a dedicated schema-to-TS generator.

Related Tools

Tool available in other languages