Generate TypeScript Interfaces from JSON Automatically

TypeScript is now the default choice for new JavaScript projects — over 70% of JS developers use it as of 2026. But every time you add a new API endpoint or change a backend schema, you face the same chore: manually updating your TypeScript interfaces to match the JSON your API returns.

This guide covers how JSON maps to TypeScript, what to watch out for (null, optional fields, arrays), and how to automate the conversion so you never hand-write an interface from a JSON response again.

Convert JSON to TypeScript interfaces instantly:

Open JSON to TypeScript →

How JSON types map to TypeScript

JSON has six value types. TypeScript has a direct equivalent for each:

JSON typeTypeScript typeExample
Stringstring"hello"
Numbernumber42, 3.14
Booleanbooleantrue
Nullnullnull
ArrayT[]string[], User[]
Objectinterfaceinterface User { ... }

A simple JSON object maps directly to a TypeScript interface:

// JSON
{
  "id": 1,
  "name": "Alice",
  "email": "alice@example.com",
  "active": true
}

// Generated TypeScript
interface Root {
  id: number;
  name: string;
  email: string;
  active: boolean;
}

Nested objects become nested interfaces

When a JSON value is itself an object, it becomes a named interface derived from the key name:

// JSON
{
  "user": {
    "id": 42,
    "address": {
      "city": "London",
      "country": "UK"
    }
  }
}

// Generated TypeScript
interface Root {
  user: User;
}

interface User {
  id: number;
  address: Address;
}

interface Address {
  city: string;
  country: string;
}

Interface names are derived from the key using PascalCase: userAddressUserAddress, api_responseApiResponse.

Arrays

Arrays of a single type become T[]. Arrays of multiple types become a union array (T | U)[]:

// JSON
{ "tags": ["admin", "editor"], "scores": [1, 2.5, 3] }

// TypeScript
interface Root {
  tags: string[];
  scores: number[];
}

Arrays of objects generate a named interface for the item type:

// JSON
{ "books": [{ "title": "Dune", "pages": 412 }] }

// TypeScript
interface Root {
  books: Book[];
}

interface Book {
  title: string;
  pages: number;
}

The null problem

null is where auto-generated interfaces need human review. A field typed as null from a single API response might actually be string | null at runtime — the response just happened to have a null value when you sampled it.

// JSON response (field happens to be null)
{ "middleName": null }

// Auto-generated (correct but incomplete)
interface Root {
  middleName: null;
}

// What it probably should be
interface Root {
  middleName: string | null;
  // or:
  middleName?: string;
}

Rule of thumb: after generating interfaces, review every null field and decide whether it should be T | null, T | undefined, or optional (?).

Optional fields

If an API response sometimes includes a field and sometimes omits it, the field should be optional in your interface:

interface User {
  id: number;
  name: string;
  avatar?: string;    // may be absent
  bio?: string | null; // may be absent or null
}

Auto-generators working from a single response cannot detect optional fields — they only see what is present. For accurate optional detection, run the generator against multiple API responses and merge the results, or consult the API schema (OpenAPI / JSON Schema).

Using generated interfaces

Once generated, paste the interfaces into a .d.ts or .ts file in your project. You can then use them for type assertions and function signatures:

// api.ts
const response = await fetch('/api/users/42');
const user: User = await response.json(); // type-safe from here
console.log(user.name);  // IDE autocomplete works

Or use the satisfies operator (TypeScript 4.9+) for safer object literals:

const user = {
  id: 42,
  name: "Alice",
} satisfies User;

When to use generated interfaces vs JSON Schema

Generated interfaceJSON Schema / OpenAPI
SpeedInstant — paste JSON, copy typesRequires schema authoring
AccuracyBased on one sample — may miss optional fieldsAuthoritative — reflects all valid states
Runtime validationNot included (compile-time only)Yes — can validate at runtime with AJV etc.
Best forRapid prototyping, known stable APIsProduction APIs, public contracts

Frequently Asked Questions

Should I use interface or type for JSON data?

Either works for simple cases. The TypeScript team's recommendation is to use interface when representing object shapes (which is what JSON objects are), and type for unions, intersections, and primitive aliases. Generated interfaces from JSON should use interface.

How do I handle a JSON array as the root element?

If your API returns an array at the root level (e.g., [{ "id": 1 }, { "id": 2 }]), the generated type will be Root[], where Root describes each item. Use it as const data: Root[] = await response.json().

What is the difference between string | null and string | undefined?

null is an explicit JSON value — it appears in the serialized response. undefined is a JavaScript concept for a missing value — it is not valid JSON and is stripped during serialization. For JSON API fields: use string | null when the API sends null, and use string? (optional) when the key may be absent entirely.

Can I use JSON Schema to generate TypeScript interfaces?

Yes. If you have an OpenAPI or JSON Schema definition, tools like json-schema-to-typescript and openapi-typescript generate accurate TypeScript types directly from the schema — including optional fields, enums, and union types. This is more reliable than generating from a single JSON sample for production code.

Generate TypeScript interfaces from your JSON in seconds:

Open JSON to TypeScript →