public-rules › TypeScript techs/typescript

Generate service types from their contracts

HIGH1.0.0
When to apply Before planning, writing, changing, or reviewing TypeScript types for external APIs, message formats, or database schemas, such as REST, GraphQL, or queue payloads.

Generate TypeScript types from each external service's machine-readable contract, such as an OpenAPI document, GraphQL schema, or database schema, instead of writing them by hand.

Implementation

  • Use a generator for the contract format, such as openapi-typescript for OpenAPI, GraphQL Code Generator for GraphQL, or the database client's type generation.
  • Regenerate as part of the build or a checked-in script, and fail CI when the generated types are out of date.
  • Do not edit generated files; change the contract or the generator configuration.
  • Write types by hand only when no contract is available, and note where the shape came from.
  • Generated types describe what the service promises; still validate untrusted responses at runtime where a wrong shape would cause damage.

Rationale

A hand-written type is a copy of the contract made once and updated by memory. When the service changes, the copy stays the same, and TypeScript approves code that fails at runtime. Generated types change with the contract, so a breaking service change becomes a compile error.

Examples

Incorrect (counterexample):

// Written by hand from the API docs last year.
type Order = { id: string; total: number };

The API now returns total as an object with amount and currency, and nothing flags the code that treats it as a number.

Correct:

import type { components } from './generated/api-types';

type Order = components['schemas']['Order'];

The type is regenerated from the OpenAPI document, so the change to total fails to compile wherever it matters.

Validation

Check that types for external services come from generated files, and that CI checks the generated files are current.

A hand-written type for a service with no available contract, with a note about its source, is not a violation.