openapi-typescript-express-plugin
v1.0.2
Published
Generate Express handler types from OpenAPI schemas, powered by openapi-typescript
Maintainers
Readme
openapi-typescript-express-plugin
Generate fully-typed Express handler types from OpenAPI 3.x schemas. Powered by openapi-typescript v7.
This package runs openapi-typescript to produce the standard type output (paths, components, operations, etc.), then appends three additional Express-specific interfaces that give you end-to-end type safety for Express route handlers.
Generated Express types
Given an OpenAPI spec, the plugin generates:
express<AppLocals, RequestLocals>-- Per-operation detail type containingrequestBody,responses,response,request, andhandlerfor each operation.pathHandlers<AppLocals, RequestLocals>-- Handler functions keyed by URL path and HTTP method.operationHandlers<AppLocals, RequestLocals>-- Handler functions keyed byoperationId.
Both generic parameters default to Record<string, any> and let you thread your app-level and request-level locals through the type system.
Installation
yarn add -D openapi-typescript-express-plugin
# or
npm install -D openapi-typescript-express-pluginYour project also needs @types/express installed for the generated types to resolve.
CLI usage
npx openapi-typescript-express-plugin ./openapi.yaml -o ./src/generated/api.tsThe output directory is created automatically if it doesn't exist.
Options
| Flag | Description |
|------|-------------|
| -o, --output <file> | Output file path (default: stdout) |
| --immutable | Generate readonly types |
| --enum | Generate TypeScript enums instead of unions |
| --alphabetize | Sort types alphabetically |
| --exclude-deprecated | Exclude deprecated fields |
Programmatic usage
import { openapiTSExpress } from 'openapi-typescript-express-plugin';
// From a file path
const types = await openapiTSExpress('./openapi.yaml');
// From a URL
const types = await openapiTSExpress('https://api.example.com/openapi.json');
// From an inline spec object
const types = await openapiTSExpress({
openapi: '3.1.0',
info: { title: 'My API', version: '1.0.0' },
paths: { /* ... */ },
});
// With openapi-typescript options
const types = await openapiTSExpress('./openapi.yaml', {
openapi: { enum: true, immutable: true },
});You can also use generateExpressTypes directly if you only need the Express type output and are running openapi-typescript separately:
import { generateExpressTypes } from 'openapi-typescript-express-plugin';
const expressTypes = generateExpressTypes(openapiSpecObject);Example output
For a spec with a GET /users/{id} endpoint (operationId: getUser), the generated Express types look like:
import type { Application, Query } from 'express-serve-static-core';
import type { Request, Response } from 'express';
export type ExpressRequest<
RequestType extends Request,
AppLocals extends Record<string, any>, Query
> = Omit<RequestType, "app" | "query"> & { app: Application<AppLocals>, query: Query };
export interface express<AppLocals extends Record<string, any>, RequestLocals extends Record<string, any>> {
getUser: {
requestBody: never;
responses: operations["getUser"]["responses"]["200"]["content"]["application/json"];
response: Response<express<AppLocals, RequestLocals>['getUser']['responses']>;
request: ExpressRequest<
Request<
operations["getUser"]["parameters"]["path"],
express<AppLocals, RequestLocals>["getUser"]["responses"] | void,
express<AppLocals, RequestLocals>["getUser"]["requestBody"],
Query,
RequestLocals
>,
AppLocals,
never>;
handler: (
req: express<AppLocals, RequestLocals>['getUser']['request'],
res: express<AppLocals, RequestLocals>['getUser']['response'],
) => void | Promise<void>;
}
}
export interface pathHandlers<AppLocals extends Record<string, any>, RequestLocals extends Record<string, any>> {
'/users/{id}': {
get: express<AppLocals, RequestLocals>['getUser']['handler'];
};
}
export interface operationHandlers<AppLocals extends Record<string, any>, RequestLocals extends Record<string, any>> {
getUser: express<AppLocals, RequestLocals>['getUser']['handler'];
}Using the generated types
import type { operationHandlers } from './generated/api.js';
// Type-safe handler with fully typed req.params, req.body, req.query, and res
const getUser: operationHandlers['getUser'] = async (req, res) => {
const { id } = req.params; // typed as { id: string }
const user = await db.users.findById(id);
res.json(user); // type-checked against the response schema
};How it works
- Calls openapi-typescript v7 to generate the standard type output (
paths,components,operations) - Parses the OpenAPI spec to walk all paths and operations
- Generates Express handler types that reference the
operationsinterface from step 1 - Combines both outputs into a single file
This approach keeps the package decoupled from openapi-typescript internals -- it consumes the public API rather than forking the codebase.
