Skip to main content

Command Palette

Search for a command to run...

Stop Hand-Writing TypeScript Interfaces for API Responses

Generate TypeScript interfaces from JSON automatically — faster and more accurate than hand-writing types for API responses.

Updated
•3 min read•View as Markdown
T
Free online tools for PDF, images, text, files, conversion and everyday developer tasks. No signup required.

Every frontend developer knows this ritual: you call a new API, get back a JSON blob with 40 fields, and then spend the next 20 minutes hand-writing an interface for it. Miss one nested object and TypeScript complains. Guess a field type wrong and you ship a bug.

There is a better way: infer the types straight from the JSON.

The problem with hand-written interfaces

Take a typical API response:

{
  "id": 42,
  "title": "Hello world",
  "published": true,
  "tags": ["webdev", "typescript"],
  "author": {
    "name": "Jane",
    "followers": 1200
  }
}

Hand-writing the interface is not hard — it is just tedious and error-prone:

interface Article {
  id: number;
  title: string;
  published: boolean;
  tags: string[];
  author: Author;
}

interface Author {
  name: string;
  followers: number;
}

Now imagine that response has six levels of nesting, arrays of objects, and a few nullable fields. This is where hand-writing stops being "quick" and starts being a source of bugs.

Generate the types instead

The reliable approach is mechanical: parse the JSON, walk its structure recursively, and emit a type for every value.

  • string, number, boolean map directly
  • null stays null
  • Arrays infer from their elements — string[] for ["a", "b"]
  • Arrays of objects get their own named interface, e.g. ArticleItem
  • Mixed arrays become unions: (number | string)[]
  • Empty arrays fall back to any[] rather than guessing wrong

A free browser-based JSON to TypeScript converter does exactly this: paste the API response, name your root type, and copy the interfaces. It also handles the options you would otherwise set by hand — interface vs. type-alias style, optional properties, and the export keyword.

If you are working with a GraphQL codebase instead, the same idea applies: a JSON to GraphQL converter turns a sample payload into SDL type definitions, which is handy when sketching a schema from a REST response you are migrating.

Edge cases worth knowing

Nullable fields. JSON has null but no "optional" concept. If a field is null in your sample, mark it optional or widen it to string | null — whichever matches your API contract.

Inconsistent arrays. Real-world APIs sometimes return [1, "2"]. A union type (number | string)[] is honest; silently picking one type is not.

Root arrays. When the response itself is an array, you still want a named root: export type Root = Item[]; keeps imports clean.

Dates. JSON has no date type — "2026-09-26" is a string. If your codebase uses Date, do a second pass and swap those fields.

A workflow that actually sticks

  1. Hit the endpoint, copy the raw JSON response.
  2. Validate and format it first so you are converting clean data.
  3. Generate the TypeScript interfaces from the JSON.
  4. Review the output — rename the auto-generated nested types (RootAuthor → Author) to match your domain language.
  5. Paste into your project and let tsc do the rest.

The review step matters. Generated types are a starting point, not a contract — your API's documentation (or its OpenAPI spec, if it has one) is the source of truth for which fields are truly optional.

Why this beats the alternatives

  • Faster than hand-writing for anything beyond a flat object.
  • More accurate — the machine reads the actual values, not your assumptions.
  • Repeatable — when the API adds a field, regenerate instead of diffing by hand.

Next time you integrate an API, skip the manual interface. Generate it, review it, ship it.