InfraHub
Back to Blog
Developer
DevOps Engineer

JSON to TypeScript: Generate Type-Safe Interfaces from API Responses

Learn how to generate TypeScript interfaces from JSON data, why type safety matters for API integration, and how to handle edge cases.

JSON to TypeScript: Generate Type-Safe Interfaces from API Responses

TypeScript's value proposition is type safety. But when you're integrating a third-party API or working with a legacy backend, you often start with raw JSON and need to build TypeScript interfaces by hand. That's tedious, error-prone, and entirely automatable.

Why TypeScript Types Matter for API Integration

Without types, every API response property access is a potential runtime error. With types, the TypeScript compiler catches mismatches before they reach production:

// Without types - runtime error waiting to happen
const name = response.data.usr.firstName;  // typo: usr vs user

// With types - caught at compile time
const name = response.data.user.firstName;  // TS error: Property 'usr' does not exist

Types also enable autocomplete in your IDE, making development faster and reducing cognitive load when working with unfamiliar APIs.

The Manual Approach (and Why It Doesn't Scale)

Given this API response:

{
  "id": 1,
  "user": {
    "name": "Alice",
    "email": "alice@example.com",
    "roles": ["admin", "editor"]
  },
  "createdAt": "2025-01-15T10:30:00Z",
  "metadata": {
    "source": "web",
    "version": 2
  }
}

You'd write:

interface Metadata {
  source: string;
  version: number;
}

interface User {
  name: string;
  email: string;
  roles: string[];
}

interface ApiResponse {
  id: number;
  user: User;
  createdAt: string;
  metadata: Metadata;
}

This is manageable for small responses. Real-world APIs often return objects with 50–100 fields, deeply nested structures, and inconsistent typing. Writing these by hand introduces errors and takes time that could be spent on actual feature work.

Type Inference Challenges

Nullable Fields

JSON doesn't distinguish between a field that's absent and one that's explicitly null. TypeScript models these differently:

// Optional (may be absent)
description?: string;

// Nullable (present but can be null)
description: string | null;

// Both
description?: string | null;

When generating types from a single JSON sample, you can't know which case applies — you need to test with multiple samples or consult the API documentation.

Number Types

JSON has a single number type, but TypeScript can use number, bigint, or enums. Auto-generated types will use number for all numeric fields.

Arrays

Arrays in JSON can be homogeneous (string[]) or heterogeneous ((string | number)[]). Type generators typically infer from the first element or produce a union type.

Deeply Nested Objects

Responses with 5+ levels of nesting generate multiple interface definitions. Good generators name these intelligently based on the property path.

Best Practices for Generated Types

  1. Review before committing: Auto-generated types are a starting point, not a final artifact. Review for nullable fields and add documentation comments.

  2. Add API version to the type name: UserV2 ages better than User when the API evolves.

  3. Use unknown over any: If a field truly can be anything, unknown is safer than any because it requires explicit type narrowing before use.

  4. Separate request and response types: An API may return more fields than it accepts. Don't reuse response types as request body types.

  5. Use Zod or io-ts for runtime validation: TypeScript types disappear at runtime. For production API integration, pair your interfaces with a runtime validator:

import { z } from 'zod';

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

type User = z.infer<typeof UserSchema>;

Generate TypeScript Interfaces from JSON

The JSON to TypeScript tool on InfraHub takes any JSON — paste it in or upload a file — and generates clean, properly nested TypeScript interfaces in seconds. It handles:

  • Nested objects (generates named sub-interfaces)
  • Arrays of objects
  • Primitive inference (string, number, boolean, null)
  • Optional vs. required field detection

All conversion happens in your browser. Your API response data never leaves your machine — important when working with payloads that contain sensitive structure information.

Use it to bootstrap your type definitions from API documentation examples, Postman responses, or database exports.

Share Feedback

We read every message