Skip to content

Getting Started

On this page, we will learn how to use tspec to generate OpenAPI Specification from TypeScript types and serve it with Swagger UI.

Installing

Assuming you have Node.js and TypeScript installed, create a new typescript project:

bash
mkdir my-project
cd my-project

Then, initialize tsconfig.json:

bash
tsc --init

Now, initialize package.json and install tspec:

bash
yarn init -y
yarn add tspec
bash
npm init -y
npm install tspec
bash
pnpm init -y
pnpm add tspec

Define ApiSpec

Tspec supports multiple ways to define API specifications depending on your framework.

ts
import { Tspec } from "tspec";

/** Schema description defined by JSDoc */
interface Book {
  /** Field description defined by JSDoc */
  id: number;
  title: string;
  description?: string;
}

export type BookApiSpec = Tspec.DefineApiSpec<{
  paths: {
    '/books/{id}': {
      get: {
        summary: 'Get book by id',
        path: { id: number },
        responses: { 200: Book },
      },
    },
  }
}>;
ts
import { Request, Response } from 'express';
import { Tspec } from 'tspec';

interface Book {
  id: number;
  title: string;
}

// Define your Express handler with typed parameters
export const getBook = async (
  req: Request<{ id: string }>,
  res: Response<Book>,
) => {
  res.json({ id: Number(req.params.id), title: 'Book Title' });
};

// Use handler type to auto-generate parameters and responses
export type BookApiSpec = Tspec.DefineApiSpec<{
  paths: {
    '/books/{id}': {
      get: {
        summary: 'Get book by id',
        handler: typeof getBook,
      },
    },
  },
}>;
ts
import { Controller, Get, Param } from '@nestjs/common';

interface Book {
  id: number;
  title: string;
}

/**
 * Books API Controller
 */
@Controller('books')
export class BooksController {
  /**
   * Get a single book by ID
   * @summary Get book by ID
   */
  @Get(':id')
  findOne(@Param('id') id: string): Promise<Book> {
    return Promise.resolve({ id: Number(id), title: 'Book Title' });
  }
}

// No need to define ApiSpec manually!
// Use `tspec generate --nestjs` to generate OpenAPI spec

Generate OpenAPI Spec

Now, let's generate OpenAPI Spec:

bash
npx tspec generate --outputPath openapi.json
bash
npx tspec generate --nestjs --outputPath openapi.json

TIP

  • Basic / Express: Tspec automatically parses Tspec.DefineApiSpec from any files that match **/*.ts.
  • NestJS: Use the --nestjs flag to parse controllers directly. Default glob is src/**/*.controller.ts.
  • For more details, see Express Integration and NestJS Integration.
Generated OpenAPI Spec

(For readability, the generated OpenAPI Spec is formatted with yaml)

yaml
openapi: 3.0.3
info:
  title: Tspec API
  version: 0.0.1
paths:
  /books/{id}:
    get:
      operationId: BookApiSpec_get_/books/{id}
      tags:
        - Book
      summary: Get book by id
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: number
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Book'
components:
  schemas:
    Book:
      description: Schema description defined by JSDoc
      type: object
      properties:
        id:
          description: Field description defined by JSDoc
          type: number
        title:
          type: string
        description:
          type: string
      required:
        - id
        - title

Serve OpenAPI Spec

Now, let's serve the OpenAPI Spec with Swagger UI:

bash
yarn tspec server --port 3000
bash
npx tspec server --port 3000
bash
pnpm tspec server --port 3000

Then, open http://localhost:3000/docs in your browser.

You will see the Swagger UI page:

Swagger UI API

And you can see schema definitions in the Schemas tab.

Swagger UI Schema