Response Handling
Each operation returns a discriminated union: either a compliant API response
(isValid: true with a status code as string, e.g. '200', '404',
'422', or a range like '4XX', '5XX') or an error object (isValid: false)
with a kind discriminator.
Validation is opt-out by default (compliant responses expose a parsed field).
You can disable automatic validation at runtime by providing
forceValidation: false in the configuration you pass to an operation or via
configureOperations.
Recommended Pattern
const result = await getPetById({ path: { petId: "123" } });
if (result.isValid === false) {
console.error("Operation failed:", result.kind, result.error);
} else if (result.status === "200") {
console.log("Pet (raw):", result.data);
} else if (result.status === "404") {
console.warn("Pet not found");
} else if (result.status === "4XX") {
console.warn("Client error (4XX):", result.data);
} else if (result.status === "5XX") {
console.error("Server error (5XX):", result.data);
} else {
console.error("Unexpected documented status", result.status);
}
Response Structure
Successful Responses
When an operation succeeds, the response object includes:
isValid: true: Indicates the operation was successfulstatus: The HTTP status code returned by the serverdata: The raw response payload from the serverparse(): Method to validate and parse the response (whenforceValidation: false)parsed: Pre-validated data with content type (whenforceValidation: true- default)- Contains
{ data: T, contentType: string }structure
- Contains
Error Responses
When an operation fails, the response object includes:
isValid: false: Indicates the operation failedkind: The type of error that occurrederror: Detailed error information specific to the error type
Validation Modes
Automatic Validation (default)
Automatic validation is enabled by default, meaning that successful responses
are validated against the OpenAPI schema and the parsed field is populated.
const result = await getPetById({ path: { petId: "123" } });
if (result.isValid && result.status === 200) {
// Data is automatically validated and includes content type
const { data, contentType } = result.parsed;
console.log("Content type:", contentType);
console.log("Pet:", data);
}
Manual Validation
Deferred manual validation is achieved by setting forceValidation: false per
operation or globally using configureOperations. See
Define Configuration section for more details.
When forceValidation: false is set, responses provide a parse() method that
you can call when needed:
const result = await getPetById({ path: { petId: "123" } });
if (result.isValid && result.status === 200) {
const outcome = result.parse();
if (isParsed(outcome)) {
console.log("Pet:", outcome.parsed);
} else {
console.error("Validation failed:", z.prettifyError(outcome.error));
}
}
Status Code Handling
The discriminated union allows you to handle different response status codes type-safely:
const result = await getPetById({ path: { petId: "123" } });
if (!result.isValid) {
console.error("Operation failed:", result.error);
return;
}
// result.data is untyped raw data here
switch (result.status) {
case "200":
console.log("Pet found (raw):", result.data);
break;
case "404":
console.log("Pet not found");
break;
case "400":
console.log("Invalid request (raw):", result.data);
break;
case "4XX":
console.log("Client error (4XX):", result.data);
break;
case "5XX":
console.log("Server error (5XX):", result.data);
break;
default:
console.log("Unexpected status:", result.status);
}
Best Practices
- Always check
isValidbefore accessing response data - Handle all expected status codes explicitly
- Use automatic validation for trusted APIs where performance isn't critical
- Use manual validation for large payloads, untrusted APIs or when you have specific validation needs
- Log unexpected status codes for debugging and monitoring