Skip to content

toomuchdesign/openapi-ts-json-schema

Repository files navigation

openapi-ts-json-schema

Build Status Npm version Coveralls

Generate TypeScript-first JSON Schemas (.ts modules with as const) directly from your OpenAPI definitions — so you can use the same schema for both runtime validation and TypeScript type inference.

Why?

Keeping OpenAPI specs, runtime validators, and TypeScript types in sync is hard.

Many teams end up maintaining the same api models in different formats:

  • JSON Schema for runtime validation (Ajv, Fastify, etc.)
  • TypeScript types for static checking

openapi-ts-json-schema solves this by generating TypeScript JSON Schemas directly from your OpenAPI definitions: valid JSON schemas written as TypeScript modules, ready for runtime validation and type inference.

These schemas:

  • ✅ are 100% JSON Schema–compatible (usable with Ajv, Fastify, etc.)
  • ✅ are TypeScript-native (as const objects you can import)
  • ✅ can be used for type inference via json-schema-to-ts
  • ✅ are generated automatically from your OpenAPI spec

In short: OpenAPI spec becomes the single source of truth for both runtime validation and TypeScript typing.

Example

From this OpenAPI definition:

components:
  schemas:
    User:
      type: object
      properties:
        id: { type: string }
        name: { type: string }
      required: [id, name]

You get this TypeScript JSON schema:

// components/schemas/User.ts
export default {
  type: 'object',
  properties: {
    id: { type: 'string' },
    name: { type: 'string' },
  },
  required: ['id', 'name'],
} as const;

Now you can use it for both runtime validation and type inference:

import Ajv from 'ajv';
import type { FromSchema } from 'json-schema-to-ts';
import userSchema from './components/schemas/User';

const ajv = new Ajv();
const validate = ajv.compile<FromSchema<typeof userSchema>>(userSchema);

const data: unknown = {};
if (validate(data)) {
  // data is now typed as { id: string; name: string }
} else {
  console.error(validate.errors);
}

How it works

Given an OpenAPI definition file, openapi-ts-json-schema:

Take a look at the Developer's notes for a few more in-depth explanations.

Installation

npm i openapi-ts-json-schema -D

Usage

Generate your TypeScript JSON schemas:

import { openapiToTsJsonSchema } from 'openapi-ts-json-schema';

const { outputPath } = await openapiToTsJsonSchema({
  openApiDocument: 'path/to/open-api-specs.yaml',
  definitionPathsToGenerateFrom: ['paths', 'components.schemas'],
});

Schemas are generated in a folder mirroring your OpenAPI layout (default: schemas-autogenerated).

Options

Property Type Description Default
openApiDocument (required) string Path to the OpenApi file (supports yaml and json). -
definitionPathsToGenerateFrom (required) string[] OpenAPI object paths to generate schemas from. Eg: ["components.schemas"]. -
refHandling "import" | "inline" | "keep" "import": generate and import $ref schemas.
"inline": inline $ref schemas.
"keep": keep $ref values.
"import"
idMapper (params: { id: string }) => string Customize generated schemas $ids and $refs values -
schemaPatcher (params: { schema: JSONSchema }) => void Dynamically patch generated JSON schemas. The provided function will be invoked against every single JSON schema node. -
outputPath string Path where the generated schemas will be saved. Defaults to /schemas-autogenerated in the same directory of openApiDocument. -
plugins ReturnType<Plugin>[] A set of optional plugins to generate extra custom output. See plugins docs. -
silent boolean Don't log user messages. false

$refs handling

Three strategies for how $refs are resolved:

refHandling option description
inline Inlines $refss, creating self-contained schemas (no imports, but possible redundancy).
import Replaces$refs with imports of the target definition
keep Leaves $refs untouched — useful if you plan to interpret $refs dynamically or use a plugin

Circular references are supported:

  • inline: circular refs are replaced with {}
  • import: resolves the JSON schema but TypeScript recursion halts (any type, TS error 7022)
  • keep: circular refs left unresolved

See tests for details.

Return values

Along with generated schema files, openapi-ts-json-schema returns metadata:

{
  // The path where the schemas are generated
  outputPath: string;
  metaData: {
    // Meta data of the generated schemas
    schemas: Map<
      // Schema internal id. Eg: "/components/schemas/MySchema"
      string,
      {
        id: string;
        // Internal unique schema identifier. Eg `"/components/schemas/MySchema"`
        $id: string;
        // JSON schema Compound Schema Document `$id`. Eg: `"/components/schemas/MySchema"`
        uniqueName: string;
        // Unique JavaScript identifier used as import name. Eg: `"componentsSchemasMySchema"`
        openApiDefinition: OpenApiObject;
        // Original dereferenced openAPI definition
        originalSchema: JSONSchema | string;
        // Original dereferenced JSON schema
        isRef: boolean;
        // True if schemas is used as a `$ref`
        shouldBeGenerated: boolean;
        // Text content of schema file
        fileContent?: string;

        absoluteDirName: string;
        // Absolute path pointing to schema folder (posix or win32). Eg: `"Users/username/output/path/components/schemas"`
        absolutePath: string;
        // Absolute path pointing to schema file (posix or win32). Eg: `"Users/username/output/path/components/schemas/MySchema.ts"`
        absoluteImportPath: string;
        // Absolute import path (posix or win32, without extension). Eg: `"Users/username/output/path/components/schemas/MySchema"`
      }
    >;
  }
}

Plugins

Extend openapi-ts-json-schema with custom generators. Currently available plugins:

  • generateSchemaWith$idPlugin
  • fastifyIntegrationPlugin

See plugins documentation 📖.

Todo

  • Consider removing required definitionPathsToGenerateFrom option in favour of exporting the whole OpenAPI definitions based on the structure defined in specs
  • Improve external #refs handling (currently being inlined and duplicated)
  • Find a way to merge multiple different OpenApi definitions consistently
  • Consider implementing an option to inline circular $refs with a configurable nesting level

Contributing

About

OpenAPI ➡️ TypeScript JSON Schema generator.

Topics

Resources

License

Stars

Watchers

Forks

Contributors 3

  •  
  •  
  •