Menu

Why Your TypeScript Types Don't Match Runtime JSON (And How to Fix It)

Manual TypeScript interfaces drift from actual API responses. Learn how to generate accurate types from JSON, handle optional fields, and prevent runtime type errors.

You just integrated a third-party API. The documentation shows a sample response. You carefully type out the TypeScript interface:

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

Your code compiles. Tests pass. You deploy to production.

Three weeks later, a QA engineer files a bug: "App crashes when loading guest users." You check the logs and see the API returned email: null for unverified accounts.

Your carefully crafted types just lied to you in production.

Debugging JSON Type Mismatch

The "Documentation vs. Reality" Gap

API documentation is often outdated or incomplete. Even when it's accurate, it shows the "happy path" — not the edge cases where fields become null, arrays are empty, or entire objects are missing.

The Three Sources of Type Drift

1. Optional Fields That Aren't Documented

The docs say email is always present. But in reality:

  • Free tier users don't have emails verified → email: null
  • Deleted accounts return partial data → email field missing entirely
  • Legacy data from 2015 → email: ""

2. Nested Complexity You Didn't Notice

You glance at the JSON and think "simple object". Then you paste it into your code and realize:

json{
  "user": {
    "profile": {
      "settings": {
        "notifications": {
          "email": { "enabled": true, "frequency": "daily" }
        }
      }
    }
  }
}

Typing this manually means writing 5 nested interfaces. Miss one level, and you get runtime crashes.

3. Array Type Ambiguity

json{
  "tags": ["javascript", "typescript"],
  "metadata": []
}

Is metadata an array of strings? Objects? Mixed types? You won't know until you inspect actual production data — or until it crashes.

The Manual Typing Trap

Let's say you decide to be thorough. You copy the JSON response and start typing:

typescriptinterface ApiResponse {
  id: number;
  name: string;
  // ... 50 more fields
}

Problems with this approach:

  1. Time-consuming: A 200-line JSON response takes 15+ minutes to type correctly.
  2. Error-prone: You'll mistype field names (userName vs username), guess wrong types (string when it should be string | null), or forget nested objects.
  3. Not maintainable: When the API changes (and it will), you have to manually diff the old and new responses to update your types.

The "any" Escape Hatch (And Why It's Worse)

Frustrated developers often do this:

typescriptconst data: any = await fetch('/api/user').then(r => r.json());

This "works" but defeats the entire purpose of TypeScript. You lose:

  • Autocomplete in your IDE
  • Compile-time error checking
  • Refactoring safety

You're back to writing JavaScript with extra steps.

How Auto-Generation Solves This

Instead of guessing or giving up, generate types directly from actual JSON responses.

The Workflow

  1. Capture Real Data: Use your browser DevTools Network tab to copy the actual API response (not the docs example).
  2. Generate Types: Paste the JSON into a converter that analyzes the structure.
  3. Get Accurate Interfaces: Receive TypeScript code that matches reality.

Example Input (Real API Response):

json{
  "id": 12345,
  "username": "alice_dev",
  "email": null,
  "roles": ["admin", "editor"],
  "metadata": {
    "lastLogin": "2025-12-10T08:30:00Z",
    "loginCount": 42
  }
}

Generated Output:

typescriptinterface RootObject {
  id: number;
  username: string;
  email: null;
  roles: string[];
  metadata: Metadata;
}

interface Metadata {
  lastLogin: string;
  loginCount: number;
}

Notice how it correctly detected:

  • email: null (not string)
  • roles: string[] (array type)
  • Nested Metadata interface

Handling Edge Cases: The Smart Type Inference

Good generators go beyond basic type detection:

Union Types for Nullable Fields

If you provide multiple JSON samples where email is sometimes null and sometimes a string, a smart tool generates:

typescriptemail: string | null;

This matches real-world APIs where fields are conditionally present.

Optional vs. Null vs. Undefined

TypeScript has three ways to express "might not be there":

typescriptinterface User {
  email?: string;        // Field might not exist
  phone: string | null;  // Field exists but value is null
  bio: string | undefined; // Explicitly undefined
}

The best approach depends on your API contract. Manual typing forces you to guess. Auto-generation from real responses gives you the truth.

Readonly Arrays and Tuples

Some APIs return fixed-length arrays (tuples):

json{
  "coordinates": [40.7128, -74.0060]
}

A naive converter gives you number[]. A better one detects the pattern and generates:

typescriptcoordinates: [number, number]; // Tuple: exactly 2 numbers

The Maintenance Problem

APIs evolve. A new field gets added. An old field becomes deprecated. If you manually maintain types, you need to:

  1. Notice the API changed (hope you have good monitoring)
  2. Find the exact difference
  3. Update your interface
  4. Update all consuming code

With auto-generation:

  1. Copy the new API response
  2. Re-generate types
  3. TypeScript compiler shows you exactly what broke

Your IDE highlights every place that needs updating. No guessing.

Security Consideration: Client-Side Generation

If you're working with internal APIs that return sensitive data (user emails, financial records), do not paste them into random online converters.

Many "free" tools upload your JSON to their servers for processing. You don't know if they log it, sell it, or leave it in an unsecured S3 bucket.

For sensitive work, prioritize local processing:

Verification Test

To check if a browser-based tool is truly client-side: disconnect your internet and try to convert. If it still works, it's processing locally. Tools like JSON to TypeScript pass this test.

Alternative: Command-Line Tools

For maximum security, use local CLI tools:

bash# Using quicktype (supports 20+ languages)
quicktype data.json -o types.ts

From URL (still downloads locally, then processes)

quicktype https://api.example.com/user -o User.ts

With options

quicktype data.json \ --lang typescript \ --out types.ts \ --just-types \ --nice-property-names
bash# Using json-schema-to-typescript (best for OpenAPI specs)
json2ts -i schema.json -o types.ts

Batch processing multiple files

for file in api-responses/*.json; do quicktype "$file" -o "types/$(basename "$file" .json).ts" done

Choosing the Right TypeScript Generator

When evaluating JSON to TypeScript tools, consider these factors:

Essential Features:

  • Automatic Type Detection: Converts 19.99 to number (not string)
  • Nested Object Support: Generates separate interfaces for complex structures
  • Union Type Inference: Detects string | null from multiple samples
  • Array/Tuple Recognition: Distinguishes string[] from [string, number]

Security Features:

  • Client-Side Processing: No server uploads (verify by disconnecting internet)
  • No Data Retention: Files processed in memory only
  • Open Source (Bonus): Allows security audits

Popular Options:

Browser-Based Tools:

  • JSON to TypeScript - Client-side, instant conversion
  • json2ts.com - Simple interface, good for quick tasks
  • transform.tools - Multi-format support (JSON/GraphQL/Flow)

Command-Line Tools:

  • quicktype - Best for production pipelines, supports 20+ languages
  • json-schema-to-typescript - Ideal for OpenAPI/JSON Schema specs
  • dtslint - Type validation and testing

IDE Built-ins:

  • VS Code: "Paste JSON as Code" extension by quicktype
  • IntelliJ IDEA: Built-in "Paste as TypeScript" feature
  • WebStorm: "Paste JSON as TypeScript interface" action

Best Practices Checklist

Before generating types from JSON:

  1. Use Real Data: Don't rely on documentation examples. Copy actual API responses from your Network tab.
  2. Test Edge Cases: If possible, capture responses for error states, empty arrays, and null fields.
  3. Validate with Multiple Samples: If you have 3 different user objects, generate types from all of them to catch optional fields.
  4. Add Strict Null Checks: Enable strictNullChecks in your tsconfig.json to catch null/undefined issues at compile time.
  5. Review Generated Code: Auto-generation is 95% accurate, but always review for business logic (e.g., should price be number or a custom Money type?).

When to Regenerate Types

Regenerate your types when:

  • The API version changes (v1 → v2)
  • You notice runtime errors related to unexpected field types
  • New fields appear in responses
  • You're integrating a new endpoint

Don't regenerate for every single API call — that's overkill. But do it whenever the contract changes.

Automated Type Generation in CI/CD

For production systems, integrate type generation into your build pipeline:

bash# In package.json scripts
{
  "scripts": {
    "generate:types": "quicktype api-responses/*.json -o src/types/",
    "prebuild": "npm run generate:types",
    "test:types": "tsc --noEmit"
  }
}
yaml# GitHub Actions example
  • name: Generate API Types
run: | curl https://api.example.com/schema > schema.json quicktype schema.json -o src/types/API.ts
  • name: Verify Types Compile
run: npm run test:types

Quick Decision Guide

For one-time API integrations (<100 fields):

  • Use browser-based tools like JSON to TypeScript for quick conversions
  • Verify client-side processing by disconnecting internet

For recurring tasks or large schemas:

  • Script with quicktype or json-schema-to-typescript
  • Add to CI/CD pipeline for automatic updates

For sensitive/regulated data:

  • Use command-line tools on local machines
  • Never upload customer data to public converters

For team workflows:

  • Commit generated types to version control
  • Use OpenAPI specs as single source of truth
  • Automate generation on API changes via webhooks

Summary

Manual TypeScript interfaces are:

  • Slow to write
  • Easy to get wrong
  • Hard to maintain

Auto-generated types from real JSON are:

  • Instant
  • Accurate to actual responses
  • Easy to update when APIs change

Next time you integrate an API:

  1. Copy the real JSON response (not docs)
  2. Generate TypeScript interfaces
  3. Enable strict null checks
  4. Let the compiler catch mismatches

Your QA team will thank you when they can't find bugs to file.


Ready to Generate Your Types?

For quick one-time conversions, try browser-based tools with client-side processing. For recurring tasks or CI/CD integration, use command-line tools like quicktype. Always verify tools don't upload sensitive API responses.

Try JSON to TypeScript Converter

EXPORT & SHARE

Export to other popular formats

IMPORT TO JSON

Convert to JSON from other types

CODE GENERATION

Generate code from JSON data

OTHER FORMATTERS

Format and beautify other code formats