GuidesClient TemplatesTypeScript Fetch

Using the typescript-fetch template

The typescript-fetch template outputs a client SDK based on the fetch api that gives the following:

  • Typed methods to call each endpoint
  • Support for passing a timeout, abort signals are still respected
  • Optionally, runtime response validation

Runtime request parameter validation is not currently supported.

See integration-tests/typescript-fetch for more samples.

Dependencies:

Install dependencies

First install the CLI and the required runtime packages to your project:

npm i --dev @nahkies/openapi-code-generator
npm i @nahkies/typescript-fetch-runtime

See also quick start guide

đź’ˇ

If you’re using an older version of NodeJS, or targeting very old web browsers, you may need a polyfill like node-fetch-native

Run generation

đź’ˇ

Experimental support for runtime response validation is available behind the --enable-runtime-response-validation flag.

npm run openapi-code-generator \
  --input ./openapi.yaml \
  --input-type openapi3 \
  --output ./src/clients/some-service \
  --template typescript-fetch \
  --schema-builder zod

Using the generated code

Running the above will output these files into ./src/clients/some-service:

  • ./client.ts: exports a class ApiClient that implements methods for calling each endpoint
  • ./models.ts: exports typescript types
  • ./schemas.ts: exports runtime parsers using the chosen schema-builder (default zod)

Once generated usage should look something like this:

const client = new ApiClient({
  basePath: `http://localhost:${address.port}`,
  defaultHeaders: {
    "Content-Type": "application/json",
    Authorisation: "Bearer: <TOKEN>", // can pass auth headers here
  },
})
 
const res = await client.createTodoListItem({
  listId: list.id,
  requestBody: {content: "test item"},
  // optionally pass a timeout (ms), or any arbitrary fetch options (eg: an abort signal)
  // timeout?: number,
  // opts?: RequestInit
})
 
// checking the status code narrows the response body types (ie: remove error types from the type union)
if (res.status !== 200) {
  throw new Error("failed to create item")
}
 
// body will be typed correctly
const body = await res.json()
console.log(`id is: ${body.id}`)