Typed Fetch Client for OpenAPI Schemas

2.2.1 · active · verified Tue Apr 21

openapi-typescript-fetch provides a robust and type-safe `fetch` client tailored for use with TypeScript definitions generated by `openapi-typescript`. It simplifies API interactions by offering strong typing for request parameters, response bodies, and error structures, directly derived from OpenAPI 3.x and Swagger 2.0 schemas. The current stable version is 2.2.1, with releases occurring incrementally as bug fixes and minor features are introduced. The project differentiates itself by deeply integrating with `openapi-typescript`'s generated types, allowing developers to configure a global fetcher instance, define per-path operations, and handle complex API error responses using discriminated unions, enhancing developer experience and reducing runtime errors. It supports middleware for request/response interception and offers utility types for introspection of operation arguments and return values. This library focuses on providing a secure and reliable way to interact with RESTful APIs in TypeScript environments, primarily for Node.js (>=12) and modern browsers.

Common errors

Warnings

Install

Imports

Quickstart

This quickstart demonstrates how to configure a typed fetch client, define specific API operations, execute them with type-safe parameters, and handle potential errors using the library's discriminated union error types.

import { Fetcher } from 'openapi-typescript-fetch';
import type { paths } from './petstore'; // Assume this is generated by 'npx openapi-typescript'

// Configure the fetcher with a base URL and optional global settings
const fetcher = Fetcher.for<paths>();
fetcher.configure({
  baseUrl: 'https://petstore.swagger.io/v2',
  init: {
    headers: {
      'Accept': 'application/json'
    }
  },
  use: [async (url, init, next) => {
    console.log(`[REQUEST] ${init.method || 'GET'} ${url}`);
    const response = await next(url, init);
    console.log(`[RESPONSE] ${url} - Status: ${response.status}`);
    return response;
  }]
});

// Define specific API operations
const findPetsByStatus = fetcher.path('/pet/findByStatus').method('get').create();
const addPet = fetcher.path('/pet').method('post').create();

async function runExample() {
  try {
    // Execute the findPetsByStatus operation with typed parameters
    const { status, data: pets } = await findPetsByStatus({
      status: ['available', 'pending'],
      // No body for GET request, but type-safe parameters are enforced
    });
    console.log(`Found ${pets.length} pets. First pet ID: ${pets[0]?.id}`);

    // Example of a POST request
    const newPet = {
      id: 987654321,
      name: 'Max',
      status: 'available',
      category: { id: 1, name: 'Dog' },
      photoUrls: ['http://example.com/max.jpg']
    };
    const addPetResult = await addPet(newPet);
    console.log(`Added pet with ID: ${addPetResult.data.id}`);

  } catch (e) {
    // Handle typed errors
    if (e instanceof addPet.Error) {
      const error = e.getActualType();
      console.error(`API Error for addPet (Status: ${error.status}):`, error.data);
    } else {
      console.error('An unexpected error occurred:', e);
    }
  }
}

runExample();

view raw JSON →