Skip to content

openapi-typesafe ​

openapi-typesafe turns OpenAPI 3.x documents into TypeScript types with Node.js. No Java, no node-gyp, no running OpenAPI server.

It is a drop-in successor to openapi-typescript 7.13, with the same CLI flags and the same Node API. Its output is compared with openapi-typescript's on 1,820 real-world documents with 28 option sets (50,960 cases): 99.99% of the outputs are the same byte for byte and 100% have the same types (compatibility report). The migration guide lists the changes: output that did not compile or had wrong types, and open string enums, a change merged upstream after 7.13.0. The difference is inside: openapi-typesafe prints types itself instead of through the TypeScript compiler API, so it works in projects on TypeScript 7 (see TypeScript 7). Coming from openapi-typescript? See the migration guide.

Release candidate

The current version is a 1.0.0 release candidate (1.0.0-rc.N); names and output can still change before 1.0.0.

The code is MIT-licensed and free to use.

TIP

New to OpenAPI? Speakeasy’s Intro to OpenAPI explains the “why” and “how” of OpenAPI.

Features ​

  • Supports OpenAPI 3.0, 3.1 and 3.2 (including advanced features like discriminators; see OpenAPI 3.2 features)
  • Generates runtime-free types
  • Loads documents from YAML or JSON, locally or remotely
  • Generates types for a large document in about a second (GitHub's REST API)
  • Works with TypeScript 5.4 and newer, including 6 and 7; the generator itself needs no TypeScript package

OpenAPI 2.x (Swagger) is not supported.

OpenAPI 3.2 features ​

A 3.2 document generates the same types as a 3.1 document with the same content, plus types for the 3.2 additions. A document that uses none of them gets the same output as before.

Experimental

The types generated for the 3.2 additions in the table below are experimental in 1.x: a minor release may change their shape, for example to match openapi-typescript once it supports 3.2. Such a change is named in the changelog. The output of documents that use none of these keys, client.QUERY() and the "query" member of HttpMethod are not experimental (Versioning).

3.2 featureGenerated types
query operationa query member after trace, only in path items that have one; client.QUERY() calls it
additionalOperationsan additionalOperations member keyed by the exact method name (SUBSCRIBE); the operations are typed, the clients do not call them
itemSchemaan itemContent map next to content, with the type of one item per media type; content keeps the schema type (or unknown)
in: querystringthe schema of its content becomes parameters.query
components.mediaTypesa mediaTypes member of components, and content entries that reference it
ts
"/trips": {
  // …
  trace?: never;
  additionalOperations: {
    SUBSCRIBE: operations["subscribe-trip"];
  };
};
// operations["subscribe-trip"]["responses"][200]
{
  headers: { [name: string]: unknown };
  content: { "application/jsonl": unknown };
  itemContent: { "application/jsonl": components["schemas"]["TripUpdate"] };
}

itemContent is not the response data: a stream such as application/jsonl is read with parseAs: "stream" and split into items by your code, which can use the item type.

A querystring parameter is sent with the client's querySerializer, which writes form fields (application/x-www-form-urlencoded). For another media type, such as JSON in the query string, pass your own querySerializer. 3.2 does not allow in: query parameters next to a querystring parameter; if a document has both, the query parameters are typed, and the generator warns about the querystring parameter with its JSON Pointer.

Other 3.2 additions do not change types: $self, itemEncoding, prefixEncoding, tag parent and kind, and discriminator.defaultMapping (the default schema still gets its own name as the discriminator value). A discriminator without propertyName adds no property type.

Examples ​

See examples

Setup ​

openapi-typesafe needs Node.js 22.12 or newer. In your project, run:

bash
npm i -D openapi-typesafe

And in your tsconfig.json, to load the types properly:

json
{
  "compilerOptions": {
    "module": "ESNext", // or "NodeNext"
    "moduleResolution": "Bundler" // or "NodeNext"
  }
}

Highly recommended

Also adding the following can boost type safety:

json
{
  "compilerOptions": {
    "noUncheckedIndexedAccess": true
  }
}

Basic usage ​

First, generate a local type file by running npx openapi-typesafe, first specifying your input document (JSON or YAML), and where you’d like the --output (-o) to be saved:

bash
# Local document
npx openapi-typesafe ./path/to/my/schema.yaml -o ./path/to/my/schema.d.ts

# Remote document
npx openapi-typesafe https://myapi.dev/api/v1/openapi.yaml -o ./path/to/my/schema.d.ts

Then in your TypeScript project, import types where needed:

ts
import type { paths, components } from "./my-openapi-3-schema"; // generated by openapi-typesafe

// Schema Obj
type MyType = components["schemas"]["MyType"];

// Path params
type EndpointParams = paths["/my/endpoint"]["parameters"];

// Response obj
type SuccessResponse =
  paths["/my/endpoint"]["get"]["responses"][200]["content"]["application/json"];
type ErrorResponse =
  paths["/my/endpoint"]["get"]["responses"][500]["content"]["application/json"];

With "moduleResolution": "NodeNext", write the extension: "./my-openapi-3-schema.js".

From here, you can use these types for any of the following (but not limited to):

  • Using an OpenAPI-supported fetch client (like openapi-typesafe-fetch)
  • Asserting types for other API request bodies and responses
  • Building core business logic based on API types
  • Validating mock test data is up-to-date with the current schema
  • Packaging API types into any npm packages you publish (such as client SDKs, etc.)

Released under the MIT License. Built on openapi-typescript, openapi-fetch and openapi-react-query.