PATTERN Cited by 2 sources
TypeScript as code-gen source of truth¶
Use TypeScript types as the primary source of truth for code-generating APIs, CLIs, SDKs, configuration schemas, MCP servers, Terraform providers, and documentation — instead of a standalone schema DSL like OpenAPI, Protobuf, or Smithy (Source: sources/2026-04-13-cloudflare-building-a-cli-for-all-of-cloudflare).
Problem¶
Classical code-gen pipelines center on a separate schema language — OpenAPI for REST, Protobuf for gRPC, Smithy for AWS APIs, ThriftIDL, etc. These DSLs work well for a single interface shape but create friction as the surface expands:
- OpenAPI describes REST only — cannot express CLI commands, RPC APIs, configuration files, or agent skills.
- Two-language tax — engineers write the schema in one DSL, consume it in TypeScript/Go/Python, and context-switch constantly.
- Tooling gap — schema DSLs have weaker IDE support, weaker type checking, and weaker linting than mainstream programming languages.
- Extension friction — adding a new concept to the schema (e.g., "this command has a local mode") often requires forking or out-of-band annotations.
Pattern¶
Define APIs, commands, and configuration as a set of TypeScript types with conventions, linting, and guardrails. Every generator (CLI, SDK, Terraform, MCP, docs) consumes these TypeScript types as its input.
- The "schema" is just normal TypeScript code in the source
tree — no separate
.yaml/.protofiles to keep in sync. - Conventions (e.g., "every resource has
get/list/create/delete") are expressed as reusable generic types or marker utility types. - Linting catches violations at compile time. Convention
rules like "always
getneverinfo" become type errors. See concepts/cli-convention-enforcement. - Existing schema standards (OpenAPI, JSON Schema) become generated outputs for REST-API-compatibility use cases, not inputs. Customers who need OpenAPI get it for free; internal teams work in TypeScript directly.
- Full IDE support (autocomplete, go-to-definition, refactor) comes for free because it's just TypeScript code.
Why this works at Cloudflare specifically¶
- "We write a lot of TypeScript at Cloudflare. It's the lingua franca of software engineering."
- Cloudflare already uses TypeScript type systems for Cap'n Web (RPC library) and Code Mode (tool calling as TypeScript function calls). The same instinct — TypeScript's type system is expressive enough to replace a schema DSL — scales to interface generation.
- Workers bindings are naturally TypeScript-typed, so the schema and the runtime speak the same language.
Scope — where this is most applicable¶
Good fit:
- Platform orgs generating multiple related interfaces from one spec (SDK + CLI + IaC + MCP).
- Teams already TypeScript-heavy.
- Orgs that want to extend schemas to cover new interface shapes (configuration, agent skills, RPC) that OpenAPI cannot express.
Less good fit:
- Polyglot ecosystems where TypeScript is not universal.
- Teams that truly only need one REST API; OpenAPI is still the shortest path to spec-generated clients.
Risk / tradeoffs¶
- TypeScript lock-in — you're committed to TypeScript in perpetuity as your schema language.
- No external standard — unlike OpenAPI, there's no industry tooling ecosystem already trained on your schema shape. Cloudflare mitigates by still generating OpenAPI as an output.
- Schema-as-code discipline — the codebase must treat schema-type files as public API; refactoring them needs the same care as any cross-repo API change.
Example¶
Cloudflare generates from one TypeScript schema:
cf CLI commands, Workers bindings,
wrangler.jsonc config, Cloudflare SDKs across languages,
Terraform provider, MCP Code Mode server, Agent Skills,
dashboard UI, developer docs, and (as an output) OpenAPI
schemas. See patterns/schema-driven-interface-generation
for how the 1-to-N generation pipeline is structured.
Seen in¶
- sources/2026-04-13-cloudflare-building-a-cli-for-all-of-cloudflare
— explicit TypeScript-as-schema choice for
cfand the platform-wide code-gen pipeline. - sources/2025-09-22-cloudflare-capn-web-rpc-for-browsers-and-web-servers — same design instinct one layer down: RPC interfaces expressed as TypeScript interfaces, not a schema DSL.