Skip to content
Converters 7 min read

JSON to TypeScript: Auto-Generate Type Definitions from API Responses

Learn how to convert JSON responses to TypeScript interfaces and types, handle nested objects, arrays, optional fields, and union types when typing external APIs.

ToolsVito Team

Why Type Your API Responses?

Untyped API responses are the most common source of runtime errors in TypeScript applications. Adding types to your API layer gives you:

  • Autocompletion for response fields in your IDE
  • Compile-time errors when you access a field that doesn't exist
  • Documentation that stays in sync with your code
  • Refactoring safety when the API structure changes

Basic JSON to TypeScript Mapping

// JSON
{
  "id": 42,
  "name": "Jane Doe",
  "email": "jane@example.com",
  "active": true,
  "score": 3.14,
  "tags": ["admin", "user"]
}

// TypeScript Interface
interface User {
  id: number;
  name: string;
  email: string;
  active: boolean;
  score: number;
  tags: string[];
}

Nested Objects

// JSON
{
  "user": {
    "id": 42,
    "address": {
      "street": "123 Main St",
      "city": "Springfield",
      "zip": "12345"
    }
  }
}

// TypeScript — define nested types separately
interface Address {
  street: string;
  city: string;
  zip: string;
}

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

interface ApiResponse {
  user: User;
}

Arrays of Objects

// JSON
{
  "items": [
    { "id": 1, "name": "Widget", "price": 9.99 },
    { "id": 2, "name": "Gadget", "price": 24.99 }
  ],
  "total": 34.98
}

// TypeScript
interface CartItem {
  id: number;
  name: string;
  price: number;
}

interface Cart {
  items: CartItem[];
  total: number;
}

Optional and Nullable Fields

Real APIs often include null values or omit fields entirely. Handle them precisely:

// JSON — avatar may be null, bio may be absent
{
  "id": 42,
  "name": "Jane",
  "avatar": null,
  "bio": "Developer"
}

// TypeScript
interface User {
  id: number;
  name: string;
  avatar: string | null;  // present but may be null
  bio?: string;           // may not be present at all
}

Union Types from Discriminated Fields

// API returns different shapes based on "type"
{ "type": "text", "content": "Hello" }
{ "type": "image", "url": "https://...", "alt": "Photo" }

// TypeScript discriminated union
type TextBlock = {
  type: "text";
  content: string;
};

type ImageBlock = {
  type: "image";
  url: string;
  alt: string;
};

type Block = TextBlock | ImageBlock;

TypeScript's control flow analysis will narrow the type automatically after checking block.type.

Handling Unknown API Shapes: Zod

TypeScript types are erased at runtime. If the API sends unexpected data, your types won't catch it. Use a runtime validation library to parse and validate:

import { z } from "zod";

const UserSchema = z.object({
  id: z.number(),
  name: z.string(),
  email: z.string().email(),
  tags: z.array(z.string()),
});

type User = z.infer<typeof UserSchema>;  // TypeScript type from Zod schema

const user = UserSchema.parse(apiResponse);  // throws if invalid

Generating Types from OpenAPI / Swagger

If your backend has an OpenAPI specification, generate TypeScript types automatically rather than writing them by hand:

# openapi-typescript
npx openapi-typescript https://api.example.com/openapi.json --output src/types/api.ts

# @hey-api/openapi-ts (generates a full typed client)
npx @hey-api/openapi-ts -i openapi.json -o src/api

Convert JSON to Types Instantly

Paste any JSON into ToolsVito's JSON to Code tool to generate TypeScript interfaces, Go structs, or Zod schemas — directly in your browser, nothing uploaded.

Try it now — free, runs in your browser

JSON to Code

JSON → TypeScript, Go & more