Skip to main content

@nest-toolbox/open-api-spec-to-ts

npm version

Generate TypeScript interfaces and enums from your OpenAPI (Swagger) specifications. Powered by json-schema-to-typescript.

Installationโ€‹

npm install @nest-toolbox/open-api-spec-to-ts

Quick Startโ€‹

import { generate } from '@nest-toolbox/open-api-spec-to-ts';

// Generate TypeScript interfaces from an OpenAPI spec
await generate('./openapi.json', './src/interfaces');

Given an openapi.json with component schemas, this creates:

  • One .ts file per schema (e.g., User.ts, Article.ts)
  • An index.ts barrel file that re-exports everything
  • Auto-generated import statements between related interfaces

Featuresโ€‹

  • ๐Ÿ“„ One file per schema โ€” each OpenAPI component schema gets its own TypeScript file
  • ๐Ÿ”— Automatic imports โ€” cross-references between schemas are resolved into proper import statements
  • ๐Ÿ“ฆ Barrel file โ€” generates an index.ts that re-exports all interfaces
  • ๐Ÿท๏ธ Enum support โ€” string enums are converted to TypeScript enums with UPPER_SNAKE_CASE names
  • ๐Ÿ”„ Self-reference handling โ€” schemas that reference themselves are handled correctly
  • ๐Ÿงน Clean output โ€” removes existing files before regenerating
  • ๐Ÿ“Š Configurable verbosity โ€” control logging output with LogLevel
  • ๐ŸŽจ Customizable formatting โ€” pass json-schema-to-typescript options for code style control

API Referenceโ€‹

generate(openApiFilePath, interfacesDirPath, options?)โ€‹

The main function that reads an OpenAPI spec and generates TypeScript files.

import { generate, LogLevel } from '@nest-toolbox/open-api-spec-to-ts';

await generate(
'./openapi.json', // path to your OpenAPI spec
'./src/interfaces', // output directory for generated files
{
verbosity: LogLevel.INFO,
style: {
singleQuote: true,
semi: true,
tabWidth: 2,
},
},
);

Parametersโ€‹

ParameterTypeDefaultDescription
openApiFilePathstring'./openapi.json'Path to the OpenAPI JSON specification file
interfacesDirPathstring'./interfaces'Output directory for generated TypeScript files
optionsPartial<Options>{}Generation options (see below)

Optionsโ€‹

Extends json-schema-to-typescript's Options with additional fields:

OptionTypeDefaultDescription
verbosityLogLevelLogLevel.NONELogging level (NONE, ERROR, INFO)
bannerCommentstring''Comment added to the top of each file
declareExternallyReferencedbooleanfalseInclude externally referenced types inline
enableConstEnumsbooleanfalseGenerate const enum instead of enum
unknownAnybooleanfalseUse unknown instead of any
strictIndexSignaturesbooleanfalseUse strict index signatures
style.singleQuotebooleantrueUse single quotes
style.semibooleantrueInclude semicolons
style.tabWidthnumber4Indentation width
style.printWidthnumber120Max line width
style.useTabsbooleanfalseUse tabs instead of spaces
style.bracketSpacingbooleantrueSpaces inside object braces

LogLevelโ€‹

Enum controlling console output verbosity.

import { LogLevel } from '@nest-toolbox/open-api-spec-to-ts';

LogLevel.NONE // 0 โ€” no output
LogLevel.ERROR // 1 โ€” errors only
LogLevel.INFO // 2 โ€” errors + info messages

Examplesโ€‹

Basic generation scriptโ€‹

// scripts/generate-types.ts
import { generate, LogLevel } from '@nest-toolbox/open-api-spec-to-ts';

async function main() {
await generate('./docs/openapi.json', './src/generated/api-types', {
verbosity: LogLevel.INFO,
});
console.log('Done!');
}

main();

Add to your package.json:

{
"scripts": {
"generate:types": "ts-node scripts/generate-types.ts"
}
}

CLI-style usage with argumentsโ€‹

// scripts/generate-types.ts
import { generate, LogLevel } from '@nest-toolbox/open-api-spec-to-ts';
import { argv } from 'yargs';

const openApiFilePath = argv.openApiPath as string || './openapi.json';
const interfacesDirPath = argv.interfacesPath as string || './interfaces';
const verbosity = (argv.verbosity as LogLevel) || LogLevel.INFO;

generate(openApiFilePath, interfacesDirPath, { verbosity });
npx ts-node scripts/generate-types.ts \
--openApiPath='./docs/api-spec.json' \
--interfacesPath='./src/types'

Generated output structureโ€‹

Given an OpenAPI spec with these schemas:

{
"components": {
"schemas": {
"User": {
"type": "object",
"properties": {
"id": { "type": "number" },
"name": { "type": "string" },
"role": { "$ref": "#/components/schemas/Role" }
}
},
"Role": {
"type": "string",
"enum": ["admin", "user", "guest"]
}
}
}
}

The generator produces:

src/interfaces/
โ”œโ”€โ”€ index.ts # export * from './User';
โ”‚ # export * from './Role';
โ”œโ”€โ”€ User.ts # import { Role } from './';
โ”‚ # export interface User { id: number; name: string; role: Role; }
โ””โ”€โ”€ Role.ts # export enum Role { ADMIN = 'admin', USER = 'user', GUEST = 'guest' }

Custom formattingโ€‹

await generate('./openapi.json', './src/types', {
verbosity: LogLevel.INFO,
unknownAny: true, // use `unknown` instead of `any`
enableConstEnums: true, // generate const enums
style: {
singleQuote: true,
semi: false, // no semicolons
tabWidth: 2,
printWidth: 80,
},
});

Integration with NestJS build pipelineโ€‹

// scripts/prebuild.ts
import { generate, LogLevel } from '@nest-toolbox/open-api-spec-to-ts';

async function prebuild() {
// Generate types from the API spec before compilation
await generate(
'./docs/openapi.json',
'./src/generated/api-types',
{ verbosity: LogLevel.INFO },
);
}

prebuild();
{
"scripts": {
"prebuild": "ts-node scripts/prebuild.ts",
"build": "nest build"
}
}