-
-
Notifications
You must be signed in to change notification settings - Fork 561
Open
Labels
enhancementNew feature or requestNew feature or requestopenapi-tsRelevant to the openapi-typescript libraryRelevant to the openapi-typescript library
Description
openapi-typescript version
7.8.0
Node.js version
v23.7.0
OS + version
macOS 15.5
Description
Hello, I’m using openapi-react-query with an OpenAPI 3.1 spec.
Some endpoints define multiple response statuses (201, 400, 422, etc.), each with a different schema. In the generated hooks (useQuery / useMutation), all possible response types are returned as a union, and TypeScript does not narrow the type automatically based on the status code.
Below is a portion of my /account/signup spec:
paths:
/account/signup:
post:
tags: ["Account"]
summary: Signup
description: Signup request
requestBody:
content:
application/json:
schema:
$ref: "#/components/schemas/SignupReq"
responses:
"201":
description: Signup success
content:
application/json:
schema:
$ref: "#/components/schemas/MsgRes"
"400":
description: Signup failed
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorMsgRes"
"422":
description: Validation failed
content:
application/json:
schema:
$ref: "#/components/schemas/ValidationErrorRes"
And here is an abridged shape of the generated TypeScript types from openapi-typescript:
export interface components {
schemas: {
SignupReq: { /* ...fields... */ };
MsgRes: { success: boolean; message: string };
ErrorMsgRes: { success: boolean; message: string };
ValidationErrorRes: {
success: false;
message: string;
error: {
issues: Array<{ code: string; path: Array<string|number>; message: string }>;
name: string;
};
};
};
}
export interface paths {
"/account/signup": {
post: {
requestBody: {
content: {
"application/json": components["schemas"]["SignupReq"];
};
};
responses: {
201: { content: { "application/json": components["schemas"]["MsgRes"] } };
400: { content: { "application/json": components["schemas"]["ErrorMsgRes"] } };
422: { content: { "application/json": components["schemas"]["ValidationErrorRes"] } };
};
};
};
}
In practice with openapi-fetch/openapi-react-query, the data remains a union:
const res = await client.POST("/account/signup", { body });
// res.data is typed as MsgRes | ErrorMsgRes | ValidationErrorRes,
// so even after checking res.response.status, TS doesn't narrow automatically.
if (res.response.status === 201) {
// I'd like res.data to be inferred as MsgRes here.
}
What I’m looking for
- Status-based automatic type narrowing (ideally a discriminated union keyed by status), e.g.:
if (res.response.status === 201) {
// data: MsgRes
} else if (res.response.status === 400) {
// error: ErrorMsgRes
} else if (res.response.status === 422) {
// error: ValidationErrorRes
}
Questions
- Is there a way to extend/implement this status-based narrowing in the current library?
(e.g., plugin, generic overrides, codegen options, etc.) - If this approach is not recommended, what is the suggested usage pattern for handling multiple response statuses?
- e.g., normalizing all error responses into a common error type, or avoiding status-based type enforcement and handling it at runtime.
Environment:
- OpenAPI: 3.1.0
- Libraries:
- "openapi-fetch": "^0.14.0",
- "openapi-react-query": "^0.5.0",
- "openapi-typescript": "^7.8.0",
Reproduction
Expected result
Required
- My OpenAPI schema is valid and passes the Redocly validator (
npx @redocly/cli@latest lint
)
Extra
- I’m willing to open a PR (see CONTRIBUTING.md)
Metadata
Metadata
Assignees
Labels
enhancementNew feature or requestNew feature or requestopenapi-tsRelevant to the openapi-typescript libraryRelevant to the openapi-typescript library
Type
Projects
Status
Accepted