Home β†’ JSON to TypeScript Guide

JSON to TypeScript: Complete Guide with Examples (2026)

πŸ“… Updated March 2026 ⏱ 8 min read πŸ‘¨β€πŸ’» For TypeScript developers

Converting JSON to TypeScript interfaces is one of the most common tasks when building typed APIs. Instead of manually writing interfaces, you can generate them automatically β€” saving time and eliminating typos. This guide covers everything: type mapping, nested objects, optional fields, arrays, generics, and best practices.

Try the Free Tool

Paste any JSON and get TypeScript interfaces instantly.

Convert JSON to TypeScript β†’

What Is a TypeScript Interface?

A TypeScript interface defines the shape of an object β€” what properties it has and what types those properties are. When you fetch JSON from an API, TypeScript has no idea what shape the response has. By creating an interface that matches your JSON structure, you get:

JSON to TypeScript Type Mapping

Every JSON value maps to a specific TypeScript type:

JSON ValueJSON TypeTypeScript TypeExample
"hello"stringstringname: string
42numbernumberage: number
3.14numbernumberscore: number
truebooleanbooleanisActive: boolean
nullnullnulldata: null
["a","b"]arraystring[]tags: string[]
[1, 2, 3]arraynumber[]ids: number[]
{...}objectinterfaceaddress: Address
[1, "a"]mixed array(number | string)[]mixed: (number | string)[]

Basic Example: Simple JSON to Interface

Start with a simple flat JSON object:

{
  "id": 1,
  "name": "Alice",
  "email": "alice@example.com",
  "age": 28,
  "isActive": true,
  "score": 9.5,
  "bio": null
}

The generated TypeScript interface:

interface User {
  id: number;
  name: string;
  email: string;
  age: number;
  isActive: boolean;
  score: number;
  bio: null;
}

Tip: If bio can be either a string or null, type it as bio: string | null instead of just null.

Nested Objects

When JSON has nested objects, the generator creates separate interfaces for each nested structure and references them:

{
  "user": {
    "id": 1,
    "name": "Alice",
    "address": {
      "street": "123 Main St",
      "city": "New York",
      "zip": "10001"
    }
  }
}

Generated TypeScript:

interface Address {
  street: string;
  city: string;
  zip: string;
}

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

interface RootObject {
  user: User;
}

Each nested object becomes its own named interface, making the code clean and reusable. The outer interface references the inner one by name.

Arrays of Objects

Arrays of objects are very common in API responses. Here's how they convert:

{
  "users": [
    { "id": 1, "name": "Alice", "role": "admin" },
    { "id": 2, "name": "Bob", "role": "user" }
  ],
  "total": 2
}

Generated TypeScript (the first array element is used to infer the item type):

interface UsersItem {
  id: number;
  name: string;
  role: string;
}

interface RootObject {
  users: UsersItem[];
  total: number;
}

Optional Fields

JSON APIs often return fields that may or may not be present. Mark these with ? in TypeScript:

interface User {
  id: number;
  name: string;
  email?: string;          // may not be present
  avatar?: string | null;  // present but possibly null
  metadata?: Record<string, unknown>;
}

The automated converter generates non-optional fields by default. After generating, review and add ? to any fields your API might omit.

Handling null Values Properly

There's an important distinction between null and undefined in TypeScript:

When your JSON shows null for a field, the real-world type is usually string | null or number | null. The generator uses null as a conservative choice β€” update it to match your actual API contract.

Real-World API Example

Here's a realistic GitHub API user response converted to TypeScript:

{
  "login": "octocat",
  "id": 1,
  "avatar_url": "https://github.com/images/error/octocat_happy.gif",
  "html_url": "https://github.com/octocat",
  "public_repos": 2,
  "public_gists": 1,
  "followers": 20,
  "following": 0,
  "created_at": "2008-01-14T04:33:35Z",
  "updated_at": "2008-01-14T04:33:35Z"
}
interface GitHubUser {
  login: string;
  id: number;
  avatar_url: string;
  html_url: string;
  public_repos: number;
  public_gists: number;
  followers: number;
  following: number;
  created_at: string;   // ISO date string β€” consider using Date
  updated_at: string;
}

Best practice: ISO date strings like "2008-01-14T04:33:35Z" are typed as string by default. If you parse them with new Date(), you can refine the type to a string that you know represents a date, or create a type alias: type ISODateString = string.

interface vs type: Which Should You Use?

Both interface and type can describe object shapes. Here's when to use each:

Use interface when…Use type when…
You want to extend it with extendsYou need union types: A | B
You want to implement it in a classYou need intersection types: A & B
Describing plain API response objectsYou need mapped/conditional types
Declaration merging is neededTuple types or primitive aliases

For JSON API responses, interface is the conventional choice. Either works.

Using Your Interface with fetch()

Once you have the interface, use it to type your API calls:

interface User {
  id: number;
  name: string;
  email: string;
}

async function getUser(id: number): Promise<User> {
  const response = await fetch(`/api/users/${id}`);
  if (!response.ok) throw new Error('Failed to fetch user');
  const data: User = await response.json();
  return data;
}

// TypeScript now knows data.name, data.email, data.id
const user = await getUser(1);
console.log(user.name); // βœ… Type-safe

Advanced: Generic API Response Wrapper

Many APIs wrap responses in a common envelope. Use generics to type it once:

interface ApiResponse<T> {
  data: T;
  status: number;
  message: string;
  pagination?: {
    page: number;
    total: number;
    perPage: number;
  };
}

// Usage:
type UserResponse = ApiResponse<User>;
type UserListResponse = ApiResponse<User[]>;

const response: UserResponse = await fetchUser(1);

TypeScript Utility Types for JSON Data

TypeScript's built-in utility types are extremely useful when working with JSON interfaces:

Best Practices

  1. Generate, then review β€” Use the tool to generate the base interface, then manually refine nullable and optional fields
  2. Keep interfaces close to their usage β€” Co-locate interface definitions with the files that use them
  3. Use unknown over any β€” For truly dynamic fields, prefer unknown which forces you to narrow the type before use
  4. Version your API types β€” When an API changes, create a new version of the interface rather than mutating the old one
  5. Share types between frontend and backend β€” Put shared interfaces in a types/ package that both sides import

Generate TypeScript interfaces instantly

Free, private, works with any JSON. No signup required.

Open JSON to TypeScript Tool β†’

Frequently Asked Questions

How do I convert JSON to TypeScript interface? +
Paste your JSON into the JSON to TypeScript tool, click Convert, and the tool instantly generates interfaces with correct TypeScript types for every field including nested objects and arrays.
Does the converter handle nested JSON objects? +
Yes. Each nested object becomes its own named interface. For example, if a user object has an address sub-object, the generator creates an Address interface and references it in the User interface as address: Address.
Should I use interface or type for JSON data? +
Both work, but interface is the conventional choice for describing plain API response objects. Use type when you need union types, intersection types, or other advanced type constructs.
How do I handle optional fields in a TypeScript interface? +
Mark optional fields with a question mark: name?: string. Fields that are sometimes null can be typed as name: string | null. Use Partial<T> to make all fields optional at once, which is useful for PATCH request bodies.
What is the difference between null and undefined in TypeScript? +
null means a value is explicitly absent. undefined means a variable has been declared but not assigned a value. In JSON, null is a valid value, but undefined is not β€” JSON.stringify strips undefined properties. Use field: string | null for nullable JSON fields and field?: string for fields that may not exist on the object.
Can I use the generated interface with Zod or other validators? +
Yes. You can use the TypeScript interface as the source of truth and infer a Zod schema from it using z.object(). Alternatively, use our JSON to Zod tool to generate a Zod schema directly from your JSON, then extract the TypeScript type with z.infer<typeof schema>.

Related Tools & Guides

JSON to Python  |  JSON to Go  |  JSON to Java  |  JSON to Rust  |  JSON Schema Tutorial  |  How to Validate JSON  |  JSONPath Tutorial