Response Types
Each operation generates a response union built from the responses you declared in the spec.
That means a handler cannot return an undocumented response shape, and a client can narrow safely on the exact outcome it received.
What gets generated
For an operation like GetTodo, generated output includes:
GetTodoResponse.tsfor the operation response union- one file per named response, such as
GetTodoSuccessResponse.ts - factory functions such as
createGetTodoSuccessResponse(...)
The operation response union
If GetTodo can return success or not found, the generated union looks like this in practice:
export type GetTodoResponse =
| IGetTodoSuccessResponse
| ITodoNotFoundErrorResponse;
Each member has a type discriminator that matches the response name.
The I prefix is only part of the generated TypeScript type name. At runtime, response.type still uses the response name from your spec, such as "GetTodoSuccess" or "TodoNotFoundError".
Factory functions make handlers safer
Generated response factories set the stable pieces for you, especially type and statusCode.
import {
createGetTodoSuccessResponse,
createTodoNotFoundErrorResponse,
} from "./api/generated";
const success = createGetTodoSuccessResponse({
body: {
id: "todo_123",
title: "Ship docs",
completed: false,
},
});
const notFound = createTodoNotFoundErrorResponse({
body: {
message: "Todo not found",
todoId: "todo_123",
},
});
That is safer than hand-writing raw status codes and response tags in every handler.
For JSON object bodies, the generated server path sets Content-Type: application/json automatically. Adding that header yourself is still fine, but it is usually conventional rather than required.
type is the main branching key
On both the server and client side, response.type is the practical way to work with the union.
switch (response.type) {
case "GetTodoSuccess":
return response.body.title;
case "TodoNotFoundError":
return response.body.message;
}
This is what makes the generated response union useful: you branch on a known set of outcomes instead of guessing from loose JSON.
Why this helps
Response types make everyday work safer because:
- handlers return documented outcomes
- clients can exhaustively handle expected outcomes
- shared responses stay consistent across operations
For deeper reuse patterns, see Shared Responses. For client-side handling, see Error Handling.