TypeScript devs, don’t let your OpenAPI client generator lie to you.

If you’re building REST API clients (or servers) with TypeScript, you expect type safety to save the day. But most existing OpenAPI-to-Typescript generators give a false sense of security, hiding pitfalls that can bite in production. After benchmarking 20+ tools, here’s what I found, and how I choose to fix it.

Poor error handling

Calling

const ret = await api.post({ ... })

should be safe, but the method signature often ignores network issues like DNS failures or timeouts. You’re forced to wrap it in a try/catch, but without clear documentation on what errors to expect, you’re left guessing. Even when documented, this approach is fragile and prevents efficient error handling as validation errors (against OpenAPI specs) end up in the same bag as network errors.

Limited handling of HTTP statuses

Most generators emit types only for 2xx responses, ignoring 4xx/5xx errors with specific payloads. If the API returns a 400 or 500 with some ProblemJson, generated TypeScript types (and/or runtime schemas) won’t reflect it, leaving you vulnerable to runtime surprises.

Multiple success responses, different payloads

Some APIs return different payloads for 200 vs. 201 status codes. Many generated clients only handle the first successful status code. Other clients either treat non-200 responses as errors, unknown or merge them into a vague union like SomeModel | SomeOtherModel, forcing further runtime checks to discriminate. What’s the point of using the generated code then?

Default responses mishandled

The smartest generators create discriminated unions for all response types (200, 201, 400, 500, etc.), but default responses (covering unspecified cases in OpenAPI) are often treated as generic errors and/or lack payload typing and validation, leading to inaccurate types.

Content-type being ignored

APIs returning multiple content types require discrimination by both status code and content-type. Afaik, no existing Typescript generator supports this. Ideally, you should be able to write:

if (r.status === 200) {
 if (r.contentType === "application/json") {
    // Typescript should know that r.data is SomeJsonModel
  } else if ( r.contentType === "application/xml") {
    // Typescript should know that r.data is SomeXmlModel
  }
}

OpenAPI Schema mismatch

OpenAPI schemas are more expressive than TypeScript types. For example, a schema defining an email string or regex pattern often becomes a plain string in TypeScript. Even tools with runtime validation struggle to support advanced OpenAPI features like string patterns or oneOf vs anyOf, leading to inaccurate types and runtime bugs.

Conclusion

After evaluating the landscape, I faced a dilemma: convince maintainers of top tools to adopt breaking changes for their thousands of users or build a new solution from scratch. I chose the latter and built an open-source TypeScript client generator that prioritizes safe, accurate types and excellent Developer Experience:

https://gunzip.github.io/apical-ts/

What’s your biggest pain point with generated OpenAPI clients / servers?

I’d love to hear your thoughts to shape this project, drop a comment, or check out the prototype!

Similar Posts