typedFetch
Type-safe wrapper around the native fetch API that returns errors as values instead of throwing exceptions.
Signature
typescript
function typedFetch<
JsonReturnType,
ErrorType extends ClientErrors = ClientErrors,
>(
url: Parameters<typeof fetch>[0],
options?: Parameters<typeof fetch>[1] & {
headers?: TypedHeaders;
method?: HttpMethods;
},
): Promise<
| { response: TypedResponse<JsonReturnType>; error: null }
| { response: null; error: ErrorType | ServerErrors | NetworkError }
>Type Parameters
| Parameter | Description |
|---|---|
JsonReturnType | Expected response body type on success |
ErrorType | Specific client error types to expect (defaults to all 4xx). Server errors (5xx) and NetworkError are always included. |
Parameters
| Parameter | Type | Description |
|---|---|---|
url | string | URL | Request | The resource URL, same as fetch() |
options | RequestInit | Request options with typed headers and method (optional, defaults to {}) |
Return Type
A discriminated union — check error to narrow:
typescript
const { response, error } = await typedFetch<User>('/api/users/1');
if (error) {
// response is null, error is ErrorType | ServerErrors | NetworkError
} else {
// error is null, response is TypedResponse<User>
const user = await response.json(); // Type: User
}Fetch API Compatibility
typedFetch has the same API as native fetch:
- All fetch options work:
method,headers,body,credentials,cache, etc. - Full
AbortControllersupport viasignal - Request timeout using
AbortSignal.timeout() - Same parameter types as native fetch
- Drop-in replacement for existing fetch calls
isHttpError
typescript
function isHttpError(error: unknown): error is BaseHttpErrorType guard that checks whether a value is an HTTP error (any BaseHttpError subclass). Prefer this over instanceof when the error may cross package boundaries.
typescript
import { isHttpError } from '@pbpeterson/typed-fetch';
if (isHttpError(error)) {
console.log(error.status, error.statusText, error.name);
}isNetworkError
typescript
function isNetworkError(error: unknown): error is NetworkErrorType guard that checks whether a value is a NetworkError.
typescript
import { isNetworkError } from '@pbpeterson/typed-fetch';
if (isNetworkError(error)) {
console.log('Connection failed:', error.message);
}statusCodeErrorMap
typescript
const statusCodeErrorMap: Map<number, HttpErrors>Maps HTTP status codes (400–511) to their corresponding error class constructors.
typescript
import { statusCodeErrorMap } from '@pbpeterson/typed-fetch';
const ErrorClass = statusCodeErrorMap.get(404); // NotFoundErrorhttpErrors
typescript
const httpErrors: readonly [BadGatewayError, BadRequestError, ...]Array of all 40 HTTP error class constructors. Useful for iteration and custom registries.
typescript
import { httpErrors } from '@pbpeterson/typed-fetch';
for (const ErrorClass of httpErrors) {
console.log(`${ErrorClass.status}: ${ErrorClass.statusText}`);
}Examples
Request Cancellation
typescript
const controller = new AbortController();
const { response, error } = await typedFetch<User[]>('/api/users', {
signal: controller.signal,
});
controller.abort();Request Timeout
typescript
const { response, error } = await typedFetch<User[]>('/api/users', {
signal: AbortSignal.timeout(5000),
});POST with Typed Headers
typescript
const { response, error } = await typedFetch<User>('/api/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer token',
},
body: JSON.stringify(userData),
credentials: 'include',
});