Validation
Validate response bodies with Zod, Valibot, ArkType, or any other Standard Schema-compatible validator.
Response validation works with any library that implements Standard Schema. fetch validates responses through validation, so any Standard Schema-compatible validator can be used.
Validation Flow
When a schema is provided:
- The HTTP request is executed.
- If the response is not ok and
throwOnFetchErroristrue(the default), aFetchErroris thrown before any parsing. - The response body is read with
response.json(). - The parsed value is validated against the provided Standard Schema.
- The validated value is returned, or validation issues are surfaced.
import { api } from "@zap-studio/fetch";
import { z } from "zod";
const UserSchema = z.object({ id: z.number(), name: z.string() });
const user = await api.get("https://api.example.com/users/1", UserSchema);
Supported Validators
Any validator that implements Standard Schema works — the schema is passed straight through, so transforms, defaults, and refinements behave exactly as the library defines them.
import { z } from "zod";
const UserSchema = z.object({
id: z.number(),
name: z.string(),
});import * as v from "valibot";
const UserSchema = v.object({
id: v.number(),
name: v.string(),
});import { type } from "arktype";
const UserSchema = type({
id: "number",
name: "string",
});Throwing Mode
By default (throwOnValidationError: true), a ValidationError is thrown when the response does not match the schema. Import it from validation.
import { api } from "@zap-studio/fetch";
import { ValidationError } from "@zap-studio/validation";
import { z } from "zod";
const UserSchema = z.object({ id: z.number(), name: z.string() });
try {
const user = await api.get("https://api.example.com/users/1", UserSchema);
console.log(user);
} catch (error) {
if (error instanceof ValidationError) {
console.error(error.issues);
} else {
throw error;
}
}
@zap-studio/validation is a runtime dependency of @zap-studio/fetch, but install it explicitly if you import from it directly.
Result Mode
Set throwOnValidationError: false to receive the Standard Schema result object — { value } on success, { issues } on failure.
import { api } from "@zap-studio/fetch";
import { z } from "zod";
const UserSchema = z.object({ id: z.number(), name: z.string() });
const result = await api.get("https://api.example.com/users/1", UserSchema, {
throwOnValidationError: false,
});
if (result.issues) {
console.error(result.issues);
} else {
console.log(result.value);
}
Validating Request Bodies
For request-body validation, validate the payload yourself before passing it to json.
import { api } from "@zap-studio/fetch";
import { standardValidate } from "@zap-studio/validation";
import { z } from "zod";
const CreateUserInputSchema = z.object({ name: z.string() });
const UserSchema = z.object({ id: z.number(), name: z.string() });
const rawInput: unknown = { name: "Ada" };
const input = await standardValidate(rawInput, CreateUserInputSchema, {
throwOnError: true,
});
const user = await api.post("https://api.example.com/users", UserSchema, {
json: input,
});
Standalone Validation
For validation outside HTTP requests, use validation directly. It also exports the StandardSchemaV1 type when you need to type schema parameters yourself.
import { standardValidate } from "@zap-studio/validation";
import type { StandardSchemaV1 } from "@zap-studio/validation";
import { z } from "zod";
const UserSchema = z.object({ id: z.number(), name: z.string() });
const input: unknown = { id: 1, name: "Ada" };
const user = await standardValidate(input, UserSchema, {
throwOnError: true,
});