Using $fetch
Low-level fetch function with optional schema validation and raw Response access.
The $fetch function provides more control over your requests. You can use it with or without schema validation, making it flexible for different use cases.
When to Use $fetch
Use $fetch instead of api.* methods when you need:
- Raw
Responseobjects for headers, status codes, or streaming - Non-JSON responses (binary files, text, HTML)
- Conditional validation based on response status
- More control over the request/response cycle
With Schema Validation
When you pass a schema, $fetch validates the response and returns typed data:
import { z } from "zod";
import { $fetch } from "@zap-studio/fetch";
const UserSchema = z.object({
id: z.number(),
name: z.string(),
email: z.string().email(),
});
const user = await $fetch("https://api.example.com/users/1", UserSchema, {
headers: {
Authorization: "Bearer token",
},
});
// user is typed as { id: number; name: string; email: string }
console.log(user.name);Without Schema Validation
When you don't pass a schema, $fetch returns the raw Response object:
import { $fetch } from "@zap-studio/fetch";
const response = await $fetch("https://api.example.com/users/1");
// response is a standard Response object
console.log(response.status); // 200
console.log(response.headers); // Headers object
const data = await response.json(); // Manual parsingFunction Signatures
$fetch has two overloaded signatures:
// With schema - returns validated data
async function $fetch<TSchema extends StandardSchemaV1>(
resource: string,
schema: TSchema,
options?: ExtendedRequestInit
): Promise<StandardSchemaV1.InferOutput<TSchema>>;
// Without schema - returns raw Response
async function $fetch(
resource: string,
options?: ExtendedRequestInit
): Promise<Response>;Extended Request Options
| Option | Type | Default | Description |
|---|---|---|---|
body | BodyInit | Record<string, unknown> | - | Request body (auto-stringified when schema is present) |
searchParams | URLSearchParams | Record<string, string> | - | Query parameters |
throwOnFetchError | boolean | true | Throw FetchError on non-2xx responses |
throwOnValidationError | boolean | true | Throw ValidationError on schema validation failures |
Plus all standard RequestInit options.
Examples
POST with JSON body
const user = await $fetch("https://api.example.com/users", UserSchema, {
method: "POST",
body: {
name: "John Doe",
email: "john@example.com",
},
});GET with query parameters
const url = new URL("https://api.example.com/users");
url.searchParams.set("page", "1");
url.searchParams.set("limit", "10");
const users = await $fetch(url.toString(), UsersSchema);Handling non-JSON responses
const response = await $fetch("https://api.example.com/file.pdf");
if (response.ok) {
const blob = await response.blob();
// Handle the binary data
}Custom headers
const user = await $fetch("https://api.example.com/users/1", UserSchema, {
headers: {
Authorization: "Bearer token",
"Accept-Language": "en-US",
"X-Request-ID": crypto.randomUUID(),
},
});Edit on GitHub
Last updated on