Prompt
How do I generate strongly typed API clients?
Latest observation
Here's how to generate strongly typed API clients, broken down by approach:
From an OpenAPI/Swagger spec (REST APIs)
- openapi-typescript / openapi-fetch — generates pure TypeScript types (no runtime code) from your OpenAPI spec, then pairs with a thin typed fetch wrapper. Popular when you want types without a heavy generated SDK.
- OpenAPI Generator — free, open-source, supports 50+ languages. Generates full client code (not just types), but output often needs manual cleanup to feel idiomatic.
- Speakeasy / Stainless / Fern — commercial-grade generators producing production-ready, idiomatic SDKs (TypeScript, Python, Go, Java, etc.) directly from your spec, with built-in retries, pagination, auth, and streaming support baked in. These are what most API-first companies (including OpenAI and Anthropic themselves) use for their official SDKs.
- NSwag / AutoRest — strong options if you're in the .NET/C# ecosystem specifically.
From a GraphQL schema
- GraphQL Code Generator (graphql-codegen) — the de facto standard; generates fully typed hooks/queries for React (Apollo, urql), typed operations for any client, and even server-side resolver types from the same schema. Point it at your schema + your .graphql query files, and it produces types that fail to compile if your query shape doesn't match the schema.
- gql.tada — newer, lighter-weight approach that infers types at the TypeScript level without a separate codegen step — types stay in sync automatically as you write queries.
From gRPC/Protobuf
- protoc with language-specific plugins (protoc-gen-go, protoc-gen-ts, protoc-gen-grpc-java, etc.) — protobuf's schema is inherently typed, so this is usually the most "native" strongly-typed client experience since the wire format and the types are defined together.
- Buf — modern tooling layer on top of protoc; handles linting, breaking-change detection, and generation in one workflow, widely preferred over raw protoc now.
General workflow regardless of protocol
- Treat your spec (OpenAPI, GraphQL schema, or .proto files) as the single source of truth — never hand-write types that could drift from the actual API.
- Run codegen as part of CI, not just locally — fail the build if the generated client doesn't match the current spec (catches breaking changes early).
- Version your generated client alongside your API version, and automate publishing to your package registry (most commercial generators — Speakeasy, Stainless, Fern — support this natively). If the API changes frequently, wire codegen into a pre-commit hook or watch mode so types never go stale during local development.
How to choose
REST + want minimal footprint → openapi-typescript for types-only, or OpenAPI Generator if you want a free full client.
REST + want a polished, publishable SDK → Speakeasy, Stainless, or Fern.
GraphQL → graphql-codegen (mature, huge ecosystem) or gql.tada (lighter, newer).
gRPC → Buf + protoc plugins for your target language.
-
Internal, same-repo TypeScript client/server → consider tRPC instead of a spec-based generator at all — it infers types directly from your server code with zero codegen step.
-
The common thread: the type generation should be automated and spec-driven, never manually maintained — hand-synced types between client and server are one of the most common sources of silent production bugs in API-based systems.
Observation history
See 2 earlier observations
Create a free Obsurfable account to unlock historical responses, model comparisons, and deeper brand intelligence.
How did Obsurfable measure this prompt?
Obsurfable records AI answers to buyer-style prompts in its research corpus (3 observations for this page). Metrics are distributions over observations, not a single static ranking.
Which AI systems does Obsurfable collect answers from?
OpenAI, ChatGPT, Google, Gemini, Google AI Mode, Anthropic, Claude, Perplexity, Grok, DeepSeek, Mistral, Copilot, and Meta AI.