Skip to content

stacksjs/ts-open-api

Social Card of this repo

npm version GitHub Actions Commitizen friendly

ts-open-api

A blazingly fast, native OpenAPI to TypeScript type generator built with Bun. Generate TypeScript types from OpenAPI 3.0 schemas with zero runtime overhead.

Why ts-open-api?

  • ⚡️ Lightning Fast - Built with Bun for maximum performance
  • 🎯 Zero Runtime - Pure TypeScript types with no runtime dependencies
  • 🔧 Highly Configurable - Extensive options for customizing output
  • 📝 JSDoc Support - Generate rich documentation from your OpenAPI schemas
  • 🎨 Transform API - Customize type generation with transform hooks
  • 🧪 Well Tested - Comprehensive test suite with 26+ test cases
  • 🚀 Native Implementation - No external dependencies for type generation

Features

  • ✅ Full OpenAPI 3.0 & 3.1 support
  • ✅ Generate types from local or remote schemas
  • ✅ Support for all schema types (objects, arrays, enums, unions, etc.)
  • ✅ Schema composition (allOf, anyOf, oneOf)
  • ✅ Reference resolution ($ref)
  • ✅ Path parameters, query parameters, and headers
  • ✅ Request bodies and responses
  • ✅ JSDoc comments with descriptions and examples
  • ✅ Readonly/immutable types
  • ✅ Custom type transformations
  • ✅ Alphabetical sorting
  • ✅ CLI and programmatic API

Installation

# Using bun
bun add -D ts-open-api

# Using npm
npm install -D ts-open-api

# Using pnpm
pnpm add -D ts-open-api

# Using yarn
yarn add -D ts-open-api

Quick Start

CLI Usage

# Generate types from a local OpenAPI schema
open-api ./openapi.json --output ./api-types.ts

# Generate from a remote schema
open-api https://api.example.com/openapi.json --output ./api-types.ts

# With options
open-api ./openapi.json \
  --output ./api-types.ts \
  --alphabetize \
  --immutable \
  --include-descriptions

Programmatic Usage

import { generateTypes } from 'ts-open-api'

await generateTypes({
  input: './openapi.json',
  output: './api-types.ts',
  alphabetize: true,
  immutable: true,
  includeDescriptions: true,
})

Node.js API

import { OpenAPITypeScriptGenerator } from 'ts-open-api'
import type { OpenAPISchema } from 'ts-open-api'

const schema: OpenAPISchema = {
  openapi: '3.0.0',
  info: { title: 'My API', version: '1.0.0' },
  paths: {
    '/users': {
      get: {
        responses: {
          '200': {
            description: 'Success',
            content: {
              'application/json': {
                schema: {
                  type: 'array',
                  items: { $ref: '#/components/schemas/User' },
                },
              },
            },
          },
        },
      },
    },
  },
  components: {
    schemas: {
      User: {
        type: 'object',
        required: ['id', 'name'],
        properties: {
          id: { type: 'string' },
          name: { type: 'string' },
          email: { type: 'string' },
        },
      },
    },
  },
}

const generator = new OpenAPITypeScriptGenerator(schema, {
  input: '',
  output: '',
  alphabetize: true,
})

const typescript = generator.generate()
console.log(typescript)

CLI Options

Option Description Default
--output <path> Output file path ./api-types.ts
--alphabetize Sort types alphabetically false
--immutable Generate readonly properties false
--silent Suppress console output false
--export-type Use export type instead of export interface false
--default-non-nullable Treat schema objects as non-nullable by default false
--additional-properties Allow arbitrary properties via index signature false
--path-params-as-types Generate path params as string literal types false
--support-array-length Support array length validation in types false
--no-header Disable header comment false
--include-descriptions Include descriptions as JSDoc comments false
--include-examples Include examples in JSDoc comments false

Programmatic API Options

All CLI options are available in the programmatic API, plus additional advanced options:

interface GeneratorOptions {
  input: string
  output: string

  // Type generation options
  exportType?: boolean
  alphabetize?: boolean
  immutable?: boolean
  additionalProperties?: boolean
  defaultNonNullable?: boolean
  pathParamsAsTypes?: boolean
  supportArrayLength?: boolean

  // Documentation options
  includeDescriptions?: boolean
  includeExamples?: boolean

  // Header options
  header?: boolean
  headerComment?: string

  // Output options
  silent?: boolean

  // Advanced options
  transform?: (schema: SchemaObject) => SchemaObject
  postTransform?: (typescript: string) => string
  inject?: string
}

Advanced Usage

Custom Transformations

Transform schemas before type generation:

await generateTypes({
  input: './openapi.json',
  output: './api-types.ts',
  transform: (schema) => {
    // Add custom logic to transform schemas
    if (schema.type === 'string' && schema.format === 'date-time') {
      // Convert all date-time strings to Date types
      return { ...schema, type: 'string', tsType: 'Date' }
    }
    return schema
  },
})

Post-Processing Generated Types

Modify the generated TypeScript code:

await generateTypes({
  input: './openapi.json',
  output: './api-types.ts',
  postTransform: (typescript) => {
    // Add custom imports or modify generated code
    return `import type { CustomType } from './custom'\n\n${typescript}`
  },
})

Inject Custom Types

Add custom type definitions at the beginning of the file:

await generateTypes({
  input: './openapi.json',
  output: './api-types.ts',
  inject: `
// Custom utility types
type Nullable<T> = T | null
type Optional<T> = T | undefined
`,
})

Custom Header

Replace the default header comment:

await generateTypes({
  input: './openapi.json',
  output: './api-types.ts',
  headerComment: `/**
 * Custom API Types
 * Generated on ${new Date().toISOString()}
 * DO NOT EDIT MANUALLY
 */`,
})

Examples

Generate Immutable Types with Descriptions

open-api ./openapi.json \
  --output ./api-types.ts \
  --immutable \
  --include-descriptions \
  --include-examples

Output:

export interface User {
  /** The unique identifier for the user */
  readonly "id": string
  /**
   * The user's full name
   * @example "John Doe"
   */
  readonly "name": string
  /** The user's email address */
  readonly "email"?: string
}

Generate Alphabetized Types

open-api ./openapi.json --output ./api-types.ts --alphabetize

Programmatic Generation with All Options

import { generateTypes } from 'ts-open-api'

await generateTypes({
  input: './openapi.json',
  output: './api-types.ts',
  alphabetize: true,
  immutable: true,
  includeDescriptions: true,
  includeExamples: true,
  exportType: true,
  transform: (schema) => {
    // Custom transformations
    return schema
  },
  postTransform: (ts) => {
    // Post-process generated TypeScript
    return ts
  },
})

Integration with Build Tools

Package.json Scripts

{
  "scripts": {
    "generate-types": "open-api ./openapi.json --output ./src/api-types.ts",
    "generate:watch": "open-api ./openapi.json --output ./src/api-types.ts --watch",
    "prebuild": "bun run generate-types"
  }
}

With Bun

// build.ts
import { generateTypes } from 'ts-open-api'

// Generate types before building
await generateTypes({
  input: './api/openapi.json',
  output: './src/generated/api-types.ts',
  alphabetize: true,
})

// Continue with your build process
await Bun.build({
  entrypoints: ['./src/index.ts'],
  outdir: './dist',
})

Comparison with openapi-typescript

Feature ts-open-api openapi-typescript
Runtime Bun (faster) Node.js
Dependencies Zero for generation Several
OpenAPI 3.0
OpenAPI 3.1
Transform API
JSDoc Support
Immutable Types
Alphabetization
Path Params
Native Code
Type Safety

Testing

bun test

The project includes comprehensive tests covering:

  • Basic schema types (string, number, boolean, array)
  • Object types with properties
  • Nested objects
  • Enum types
  • Nullable types
  • Composition types (allOf, anyOf, oneOf)
  • Reference resolution
  • Path operations
  • Parameters and request bodies

TypeScript Configuration

For best results, use these TypeScript settings:

{
  "compilerOptions": {
    "module": "ESNext",
    "moduleResolution": "Bundler",
    "noUncheckedIndexedAccess": true,
    "strict": true
  }
}

Changelog

Please see our releases page for more information on what has changed recently.

Contributing

Please see CONTRIBUTING for details.

Community

For help, discussion about best practices, or any other conversation that would benefit from being searchable:

Discussions on GitHub

For casual chit-chat with others using this package:

Join the Stacks Discord Server

Postcardware

“Software that is free, but hopes for a postcard.” We love receiving postcards from around the world showing where Stacks is being used! We showcase them on our website too.

Our address: Stacks.js, 12665 Village Ln #2306, Playa Vista, CA 90094, United States 🌎

Sponsors

We would like to extend our thanks to the following sponsors for funding Stacks development. If you are interested in becoming a sponsor, please reach out to us.

License

The MIT License (MIT). Please see LICENSE for more information.

Made with 💙

About

OpenAPI TypeScript automations.

Topics

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Releases

No releases published

Sponsor this project

  •