Introduction
Learn about what-the-fetch – a type-safe API client with schema validation using Standard Schema
what-the-fetch is a type-safe API client library that integrates schema validation with fetch requests, leveraging the Standard Schema specification for maximum flexibility and type safety.
Why what-the-fetch?
Building API clients manually is error-prone and lacks type safety. what-the-fetch handles type-safe URL construction, automatic request/response validation, and full TypeScript inference automatically.
Why what-the-fetch?
Building API clients manually is tedious and error-prone. what-the-fetch solves common problems developers face when working with APIs:
Problems with Manual API Clients
- 🔴 No type safety: Response types are unknown, leading to runtime errors
- 🔴 Manual validation: You need to write validation code for every endpoint
- 🔴 Schema duplication: Types and validation logic are often duplicated
- 🔴 URL building errors: String concatenation leads to malformed URLs
- 🔴 Poor developer experience: No autocomplete, no compile-time checks
How what-the-fetch Solves These Issues
what-the-fetch provides a complete solution for type-safe API clients:
-
End-to-end type safety:
- Full TypeScript inference from schema to response
- Compile-time validation of requests
- Autocomplete for all API endpoints and parameters
- Type-safe path and query parameters
-
Schema validation:
- Built-in support for Standard Schema specification
- Works with Zod, Valibot, ArkType, and more
- Automatic request/response validation
- Single source of truth for types and validation
-
Clean API:
- Simple, intuitive interface
- Integrated with fast-url library for clean URL construction
- Minimal boilerplate code
- Focus on developer experience
-
Production-ready:
- Comprehensive test coverage
- Small bundle size
- Battle-tested in real-world applications
- Regular updates and maintenance
Key Features
Type-Safe
Full TypeScript support with end-to-end type inference from schema definition to response data
Schema Validation
Built-in support for Standard Schema - compatible with Zod, Valibot, ArkType, and more
Flexible
Works with any schema library that implements Standard Schema for maximum flexibility
Minimal
Small bundle size with minimal dependencies - only fast-url library and Standard Schema spec
URL Building
Integrated with fast-url library for clean, safe URL construction with path and query parameters
Developer Experience
Excellent developer experience with full autocomplete and compile-time error checking
The Problem
Building API clients manually lacks type safety and validation:
// ❌ No type safety, manual validation
const response = await fetch(`${baseUrl}/users/${id}?fields=${fields}`);
const data = await response.json();
// What type is data? Who knows! Runtime errors waiting to happenIssues with manual API clients:
- 🔴 No type safety for request parameters
- 🔴 Unknown response types
- 🔴 Manual validation required
- 🔴 Schema and types are duplicated
- 🔴 Difficult to maintain and refactor
The Solution
what-the-fetch provides a type-safe API client with automatic validation:
// ✅ Type-safe with validation
import { createFetch } from 'what-the-fetch';
import { z } from 'zod';
const api = {
'/users/:id': {
params: z.object({ id: z.number() }),
query: z.object({ fields: z.string().optional() }),
response: z.object({ id: z.number(), name: z.string(), email: z.string() })
}
};
const apiFetch = createFetch(api, baseUrl);
const user = await apiFetch('/users/:id', {
params: { id },
query: { fields }
});
// user is fully typed as { id: number; name: string; email: string }Benefits:
- ✅ Full end-to-end type safety
- ✅ Automatic request/response validation
- ✅ Single source of truth for types and validation
- ✅ Clean separation of concerns
- ✅ Easy to read and maintain
Type Safety & Validation
what-the-fetch handles type-safe URL construction, automatic validation, and full TypeScript inference - catching errors at compile time instead of runtime.
When to Use what-the-fetch
what-the-fetch is ideal for:
- 🌐 REST API clients: Building type-safe wrappers around REST APIs
- 🔗 Microservices: Creating typed clients for service-to-service communication
- 📱 Frontend applications: Type-safe data fetching with validation
- 🛠️ Backend services: Calling external APIs with full type safety
- 📊 SDK development: Building SDKs with excellent developer experience
Quick Example
Here's a real-world example showing how what-the-fetch simplifies API client development:
import { createFetch } from 'what-the-fetch';
import { z } from 'zod';
// Define API schema once (methods inferred automatically)
const api = {
'/users/:id': { // GET (no body)
params: z.object({ id: z.number() }),
query: z.object({ fields: z.string().optional() }),
response: z.object({
id: z.number(),
name: z.string(),
email: z.string()
})
},
'/users': { // POST (has body)
body: z.object({ name: z.string(), email: z.string() }),
response: z.object({ id: z.number(), name: z.string() })
}
};
const apiFetch = createFetch(api, 'https://api.example.com');
// Type-safe GET request with validation
const user = await apiFetch('/users/:id', {
params: { id: 123 },
query: { fields: 'name,email' }
});
// user is typed as { id: number; name: string; email: string }
// Type-safe POST request (method inferred from body)
const newUser = await apiFetch('/users', {
body: { name: 'John', email: 'john@example.com' }
});// Define types manually
interface User {
id: number;
name: string;
email: string;
}
// Build URL manually
const url = `https://api.example.com/users/${id}?fields=${fields}`;
const response = await fetch(url);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
// Manual validation required
if (typeof data.id !== 'number' ||
typeof data.name !== 'string' ||
typeof data.email !== 'string') {
throw new Error('Invalid response');
}
const user: User = data;
// No compile-time guarantees that data matches User type