Skip to content

Typed FetchType-safe HTTP client that never throws

Inspired by Go's error handling pattern, built on top of the native Fetch API

Quick Example

typescript
import { typedFetch, NotFoundError, UnauthorizedError, NetworkError } from '@pbpeterson/typed-fetch';

interface User {
  id: number;
  name: string;
  email: string;
}

// Specify expected client errors for better type safety
type ExpectedErrors = NotFoundError | UnauthorizedError;
const { response, error } = await typedFetch<User[], ExpectedErrors>('/api/users');

if (error) {
  // Here, response is null and error contains the specific error
  if (error instanceof NotFoundError) {
    console.log('Users not found');
  } else if (error instanceof UnauthorizedError) {
    console.log('Authentication required');
  } else if (error instanceof NetworkError) {
    console.log('Network error:', error.message);
  } else {
    // Server errors (5xx) are always included
    console.log(`HTTP ${error.status}: ${error.statusText}`);
  }
} else {
  // Here, error is null and response contains the successful result
  const users = await response.json(); // Type: User[]
  console.log('Users:', users);
}

Why typed-fetch?

Traditional fetch libraries throw exceptions on HTTP errors, making error handling cumbersome and error-prone. typed-fetch follows Go's philosophy of explicit error handling - errors are values, not exceptions.

typescript
try {
  const response = await fetch('/api/users');
  const users = await response.json(); // What if response is 404?
} catch (error) {
  // Handle network errors, parsing errors, HTTP errors... all mixed together
}
typescript
import { NotFoundError, UnauthorizedError } from '@pbpeterson/typed-fetch';

// Specify expected errors for better type safety
type ExpectedErrors = NotFoundError | UnauthorizedError;
const { response, error } = await typedFetch<User[], ExpectedErrors>('/api/users');

if (error) {
  // Here: error has the specific error, response is null
  if (error instanceof NotFoundError) {
    console.log('Users endpoint not found');
  } else if (error instanceof UnauthorizedError) {
    console.log('Authentication required');
  } else {
    console.log(`Server error ${error.status}: ${error.statusText}`);
  }
  const errorDetails = await error.json(); // Access error response body
} else {
  // Here: response has the data, error is null
  // TypeScript knows response is not null
  const users = await response.json(); // Type: User[]
}

Installation

bash
npm install @pbpeterson/typed-fetch
bash
pnpm add @pbpeterson/typed-fetch
bash
yarn add @pbpeterson/typed-fetch

Ready to get started?

Check out the Getting Started guide to learn how to use typed-fetch in your project.

Released under the MIT License.