openapi3-ts builds OpenAPI contracts in TypeScript, one module per spec version
TS Model & utils for creating and exposing OpenAPI 3.x contracts.
At a glance
- What is it?
- openapi3-ts is a TypeScript library for writing OpenAPI 3.x contracts as code, offering typed interfaces for the document model and a fluent builder, and since version 4 it ships separate implementations for OAS 3.0, 3.1 and 3.2 so each dialect is imported deliberately. It suits teams who want the contract in the same repository and language as the server code, and its cost is that you are describing the specification rather than consuming it from a generator.
- Who is it for?
- Teams that keep their API contract in the same repository as the implementation, and who want the contract written and reviewed as ordinary TypeScript rather than generated from it, are the people openapi3-ts is for, and the per-version modules are the feature that makes it usable at all, since a 3.0 document and a 3.1 document are not the same shape.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 9 days ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 24, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The contract is code, not a document someone edits
The library's premise is that an OpenAPI contract should be written in TypeScript, and the repository description says it in one line: a TypeScript library to help building OpenAPI 3.x compliant API contracts. The readme says it is a library to help building OpenAPI 3.x compliant API contracts, and the two halves of what it includes are a set of typed interfaces under src/model for helping build a contract, and a fluent DSL under src/dsl for building a contract. The practical difference from a YAML file is that the contract gets type checking, gets reviewed in a pull request like code, and can reuse the TypeScript definitions the server already has. The cost is equally concrete, since a contract written this way is authored rather than derived, so a server that changes its types does not automatically change its published contract, and the two have to be kept in step by hand.
Version 4 split the dialects into separate implementations
The breaking change notice for version 4 is the most important thing in the readme. Version 4.0 adds explicit support for OAS 3.0 and OAS 3.1 as separate implementations, and OAS 3.2 is available as a third parallel implementation named oas32. The details of what 3.2 adds are listed, and they are not trivial: the JSON Schema dialect is unchanged between 3.1 and 3.2, still Draft 2020-12, while 3.2 adds document structure fields such as streaming itemSchema, itemEncoding and prefixEncoding on the Media Type Object, the reusable mediaTypes component bucket, the query HTTP method and additionalOperations, tag hierarchies, the XML nodeType, and the OAuth device authorization flow. The unchanged schema dialect between 3.1 and 3.2 is the detail worth remembering, because it means the two newest versions differ in document structure rather than in how values are described.
Choosing a dialect means choosing an import, not setting a flag
The import surface is what enforces the choice, and it is worth reading as a design decision rather than an inconvenience. For the 3.2 implementation you import the oas32 export, or import directly from the oas32 subpath, and the same pattern applies to oas31 and oas30. Each subpath exposes the OpenAPIObject type and the OpenApiBuilder, so a project that publishes a 3.1 document and a project that publishes a 3.2 document write the same line of code with a different name.
import { oas32 } from 'openapi3-ts';import { OpenAPIObject, OpenApiBuilder } from 'openapi3-ts/oas32';import { oas31 } from 'openapi3-ts';import { oas30 } from 'openapi3-ts';Because the implementations are parallel rather than layered, a codebase that needs to publish two dialects imports two modules and accepts that they are distinct type universes.
Installation is one npm command, and the exports map is explicit
The install is a single line, and the package metadata shows that the distribution is built for both module systems and for the subpath imports the readme documents.
npm i --save openapi3-tsThe exports map in the package metadata has an entry for the root and one for each of the three dialects, and each dialect entry declares types, an import condition pointing at an ESM build and a require condition pointing at a CommonJS one. The root entry does the same. That matters more than it looks, because a bundler that resolves the root import gets everything, while a consumer that wants only one dialect imports the subpath and gets one. The build itself is a vite build followed by a TypeScript declaration emit, and the top level of the repository carries a declaration file per dialect, named oas30.d.ts, oas31.d.ts and oas32.d.ts, so the three type surfaces are visible without opening the package.
The fluent DSL and the typed model solve different problems
Within one dialect there are two routes to a document, and they are not interchangeable in practice. The typed interfaces are for describing the shape of a contract, so you can hold an OpenAPIObject in a typed variable, build parts of it in your own functions and compose them. The fluent DSL is for the document itself, so you chain calls and end up with an object. A team that generates large documents from a set of reusable schema fragments will spend most of its time in the model layer, because that is where the typing pays off, and a team that wants a small explicit document will use the builder. The readme points at the docs directory for the details, and the repository ships a docs folder alongside a Changelog.md for version history. The credit line names Pedro J. Molina at Metadev S.L. and contributors, with the copyright running from 2017 to 2026.
The build pipeline runs lint, build and tests before publishing
The package scripts show a release process that is stricter than the readme suggests. The publish script runs build:all, which cleans the dist directory, runs the lint step over the source, builds, and runs the tests, and only then publishes. The build step is a vite build followed by a TypeScript declaration-only emit, so the type declarations are produced by tsc rather than by a bundler plugin, which tends to produce cleaner output for a library whose whole value is its types. The tests run under vitest, with a watch mode for development, a coverage mode, and a version script that prints the versions of node, npm, eslint, tsc, vite and vitest together, which is a quick way to see whether a local toolchain matches what CI used. The repository also carries a .travis.yml file, an eslint flat config and a prettier configuration.
Where openapi3-ts is the wrong choice
The first wrong case is a team whose contract is the source of truth and whose types are generated from it, because this library inverts that relationship, and a team that has invested in a generator and a linting step on the generated output will get more from that than from writing the contract by hand. The second is a project that only consumes contracts, since reading an existing document is a different problem, and a runtime validator or a generated client is the right tool. The third is a team that needs to publish a 3.0 and a 3.1 document from a single source, because the parallel implementations mean two type universes rather than one document that adapts. The fourth is a team that wants the contract to be reviewed as a specification rather than as code, since a diff of a TypeScript builder is a diff of code. The fifth is a team that expects an active upstream to merge fixes, because the newest tagged release in the repository list is v3.0.0 from 2022 while the package metadata is at 4.6.2, so the versioning history is something to look at before you depend on the release cadence.
Editorial conclusion
Teams that keep their API contract in the same repository as the implementation, and who want the contract written and reviewed as ordinary TypeScript rather than generated from it, are the people openapi3-ts is for, and the per-version modules are the feature that makes it usable at all, since a 3.0 document and a 3.1 document are not the same shape. It is the wrong choice for a team whose contract is the source of truth and whose server code should be generated from it, because here the direction is reversed, and it is the wrong choice for a team that only needs to read an existing contract, since parsing a document is a different job from authoring one. Check three things before you adopt it: which dialect your published document actually is, since the 3.0, 3.1 and 3.2 modules are separate implementations rather than one with flags, that your build can consume the subpath exports the readme documents, and that the fluent DSL fits the way your team writes code, because a builder that nobody likes is a worse outcome than a hand written YAML file. The licence is MIT, the last push was on 2026-10-15, and the package version in the repository metadata is 4.6.2 while the newest tagged release listed is v3.0.0 from 2022, which tells you the project ships under a different scheme than its npm tags.
Frequently asked questions
What is openapi3-ts and what does it include?
It is a TypeScript library to help building OpenAPI 3.x compliant API contracts. It includes typed interfaces for helping build a contract under src/model, and a fluent DSL for building a contract under src/dsl.
How do I install openapi3-ts?
With npm i --save openapi3-ts. The package is published with an exports map offering the root entry plus a subpath for each dialect, each with types, an ESM import condition and a CommonJS require condition.
How do I use the OpenAPI 3.1 implementation?
Import the oas31 export from openapi3-ts, or import OpenAPIObject and OpenApiBuilder directly from the openapi3-ts/oas31 subpath. Since version 4.0 the OAS 3.0 and OAS 3.1 support are separate implementations, and OAS 3.2 is a third parallel implementation named oas32.
What does OpenAPI 3.2 add over 3.1 in openapi3-ts?
The JSON Schema dialect is unchanged between 3.1 and 3.2, still Draft 2020-12. Version 3.2 adds document structure fields such as streaming itemSchema, itemEncoding and prefixEncoding on the Media Type Object, the reusable mediaTypes component bucket, the query HTTP method and additionalOperations, tag hierarchies, the XML nodeType, and the OAuth device authorization flow.
What licence is openapi3-ts released under?
The MIT License, stated in the readme and the LICENSE file at the root of the repository. The credits name Pedro J. Molina at Metadev S.L. and contributors, with the copyright running from 2017 to 2026.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/metadevpro-openapi3-ts)Was this useful?