Skip to main content

TypeDoc vs JSDoc vs API Extractor: TypeScript Documentation Generators (2026)

·PkgPulse Team

TL;DR

TypeDoc generates beautiful HTML documentation directly from TypeScript types and JSDoc comments — the standard for TypeScript library documentation. JSDoc is the language-agnostic comment standard that both TypeDoc and API Extractor read, plus a standalone doc generator for JavaScript projects. API Extractor (Microsoft) is for library authors — it generates the canonical public API surface (d.ts rollup), detects breaking changes, and produces API reports for review. For documenting a TypeScript package: TypeDoc. For managing a library's public API contract: API Extractor. For JavaScript-only projects: JSDoc standalone.

Key Takeaways

  • typedoc: ~3M weekly downloads — TypeScript-native HTML docs, reads types + JSDoc
  • jsdoc: ~5M weekly downloads — the comment standard; also a standalone HTML generator
  • @microsoft/api-extractor: ~15M weekly downloads — d.ts rollup, API reports, breaking change detection
  • TypeDoc and JSDoc solve "generate readable docs from your code"
  • API Extractor solves "enforce public API contracts and detect breaking changes"
  • API Extractor produces api-report.md files that review breaking changes in PRs
  • Most TypeScript library authors use TypeDoc for docs + API Extractor for API management

PackageWeekly DownloadsHTML Docsd.ts RollupAPI ReportsBreaking Change Detection
typedoc~3M
jsdoc~5M
@microsoft/api-extractor~15M

TypeDoc

TypeDoc — the standard for TypeScript HTML documentation:

Setup

npm install -D typedoc
// typedoc.json
{
  "entryPoints": ["src/index.ts"],
  "out": "docs",
  "plugin": [],
  "name": "PkgPulse SDK",
  "readme": "README.md",
  "excludePrivate": true,
  "excludeProtected": false,
  "excludeInternal": true,
  "includeVersion": true,
  "theme": "default"
}
// package.json
{
  "scripts": {
    "docs": "typedoc",
    "docs:watch": "typedoc --watch"
  }
}

JSDoc comments (TypeDoc reads these)

/**
 * Calculate the health score for an npm package based on various metrics.
 *
 * The health score considers download trends, maintenance activity,
 * dependency count, and TypeScript support.
 *
 * @param packageName - The npm package name (e.g., "react")
 * @param options - Optional configuration for the calculation
 * @param options.weights - Custom weights for each metric (must sum to 1.0)
 * @param options.includeDeprecated - Include deprecated packages in comparison
 * @returns A promise resolving to the health score (0-100) and detailed breakdown
 *
 * @example
 * ```typescript
 * const health = await getPackageHealth("react")
 * console.log(health.score)     // 95
 * console.log(health.breakdown) // { downloads: 98, maintenance: 92, ... }
 * ```
 *
 * @throws {PackageNotFoundError} If the package doesn't exist in npm registry
 * @throws {RateLimitError} If the npm API rate limit is exceeded
 *
 * @see {@link https://www.pkgpulse.com/docs/health-score} Health Score Documentation
 * @since 2.0.0
 */
export async function getPackageHealth(
  packageName: string,
  options?: HealthScoreOptions
): Promise<PackageHealth> {
  // Implementation
}

TypeDoc annotations

/**
 * Configuration for the PkgPulse SDK client.
 *
 * @remarks
 * The `apiKey` is required. Get yours at {@link https://www.pkgpulse.com/api-keys}.
 *
 * @example
 * ```typescript
 * const client = new PkgPulseClient({
 *   apiKey: process.env.PKGPULSE_API_KEY!,
 *   baseUrl: "https://api.pkgpulse.com",
 *   timeout: 5000,
 * })
 * ```
 */
export interface PkgPulseConfig {
  /** API key from pkgpulse.com/api-keys */
  apiKey: string

  /**
   * Base URL for the API.
   * @defaultValue "https://api.pkgpulse.com"
   */
  baseUrl?: string

  /**
   * Request timeout in milliseconds.
   * @defaultValue 10000
   */
  timeout?: number

  /**
   * @internal
   * Not part of the public API — used for testing.
   */
  _mockMode?: boolean
}

/**
 * Supported alert types for package monitoring.
 * @enum
 */
export type AlertType =
  /** Triggered when weekly downloads drop by more than the threshold percentage */
  | "downloads_drop"
  /** Triggered when a new version is published */
  | "version_update"
  /** Triggered when a security vulnerability is reported */
  | "security"

Deploy to GitHub Pages

# .github/workflows/docs.yml
name: Deploy Docs

on:
  push:
    branches: [main]

jobs:
  docs:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 22
      - run: npm ci
      - run: npm run docs
      - uses: peaceiris/actions-gh-pages@v3
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          publish_dir: ./docs

JSDoc

JSDoc — the universal documentation comment standard:

JSDoc as a comment standard (used by everyone)

/**
 * Fetches package download statistics from the npm registry.
 *
 * @param {string} packageName - npm package name
 * @param {"last-week"|"last-month"|"last-year"} period - Time period
 * @returns {Promise<{downloads: number, start: string, end: string, package: string}>}
 * @throws {Error} If the package doesn't exist
 *
 * @example
 * const stats = await getDownloadStats("react", "last-week")
 * console.log(stats.downloads) // 45000000
 */
async function getDownloadStats(packageName, period = "last-week") {
  const res = await fetch(
    `https://api.npmjs.org/downloads/point/${period}/${packageName}`
  )
  if (!res.ok) throw new Error(`Package ${packageName} not found`)
  return res.json()
}

JSDoc with TypeScript (type checking from comments)

// @ts-check — enables TypeScript checking in JavaScript files

/**
 * @typedef {Object} PackageHealth
 * @property {string} name - Package name
 * @property {number} score - Health score 0-100
 * @property {boolean} deprecated - Whether the package is deprecated
 * @property {string[]} tags - Associated tags
 */

/**
 * @param {string} name
 * @returns {Promise<PackageHealth>}
 */
async function getHealth(name) {
  // TypeScript will type-check this based on the @returns annotation
}

JSDoc standalone generator

// jsdoc.json (config file for jsdoc HTML generator)
{
  "source": {
    "include": ["src/"],
    "includePattern": ".+\\.js(doc)?$",
    "excludePattern": "(^|\\/|\\\\)_"
  },
  "plugins": ["plugins/markdown"],
  "templates": {
    "cleverLinks": false,
    "monospaceLinks": false
  },
  "opts": {
    "destination": "./docs/",
    "recurse": true,
    "readme": "README.md"
  }
}

API Extractor

@microsoft/api-extractor — for TypeScript library authors:

Setup

npm install -D @microsoft/api-extractor
npx api-extractor init  # Creates api-extractor.json
// api-extractor.json
{
  "$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json",
  "mainEntryPointFilePath": "<projectFolder>/dist/index.d.ts",
  "apiReport": {
    "enabled": true,
    "reportFolder": "<projectFolder>/etc/"  // Store in git — review changes in PRs
  },
  "docModel": {
    "enabled": true,
    "apiJsonFilePath": "<projectFolder>/temp/<unscopedPackageName>.api.json"
  },
  "dtsRollup": {
    "enabled": true,
    "untrimmedFilePath": "<projectFolder>/dist/<unscopedPackageName>-untrimmed.d.ts",
    "publicTrimmedFilePath": "<projectFolder>/dist/<unscopedPackageName>.d.ts"
  },
  "tsdocMetadata": { "enabled": true }
}

What API Extractor generates

// API Report (etc/pkgpulse-sdk.api.md) — committed to git:
// This file is checked to detect breaking changes in PRs.

// After running api-extractor run:

/* etc/pkgpulse-sdk.api.md */
// @public
export function getPackageHealth(packageName: string, options?: HealthScoreOptions): Promise<PackageHealth>;

// @public
export interface PackageHealth {
    breakdown: HealthBreakdown;
    name: string;
    score: number;
}

// @internal (not included in public .d.ts rollup)
export function _internalHelper(): void;

Breaking change detection in CI

# .github/workflows/api-review.yml
- name: Run API Extractor
  run: npx api-extractor run --local --verbose

# If the public API changed (api-report.md would differ from committed version):
# → API Extractor exits with error code
# → PR fails until the api-report.md is updated and committed
# → Forces explicit review of all breaking changes

API annotations

/**
 * @public — included in public .d.ts
 */
export function getPackageHealth(name: string): Promise<PackageHealth> { ... }

/**
 * @beta — public but not stable
 */
export function getExperimentalMetrics(name: string): Promise<unknown> { ... }

/**
 * @alpha — very early, may change frequently
 */
export function _dangerousLowLevelAccess(): void { ... }

/**
 * @internal — stripped from public .d.ts rollup
 */
export function _privateHelper(): void { ... }

/**
 * @deprecated Use getPackageHealth() instead.
 */
export function getHealth(name: string): Promise<PackageHealth> { ... }

Feature Comparison

FeatureTypeDocJSDoc (standalone)API Extractor
HTML documentation✅ Beautiful✅ Basic
TypeScript-native❌ (comment-based)
d.ts rollup
Breaking change detection
API reports
Plugins✅ Rich
@alpha/@beta/@internal
Markdown integration
CI integration

When to Use Each

Choose TypeDoc if:

  • Publishing a TypeScript library on npm and want HTML docs
  • You want docs generated from your TypeScript types directly
  • Deploying documentation to GitHub Pages or a docs site
  • The standard choice for TypeScript library documentation

Choose JSDoc (comments) everywhere:

  • JSDoc comments are read by TypeDoc, API Extractor, VS Code IntelliSense, and TypeScript
  • Even if you never run jsdoc standalone, add JSDoc comments to all exported functions
  • Use JSDoc standalone for pure JavaScript libraries (not TypeScript)

Choose API Extractor if:

  • Publishing a TypeScript library with a stable public API
  • You want to detect breaking changes in PRs before they ship
  • Your library has multiple consumers who rely on API stability
  • You need a clean d.ts rollup (single file instead of many)
  • Working at an organization with formal API review processes

Common pattern for npm library authors:

TypeDoc → HTML docs hosted on GitHub Pages
API Extractor → d.ts rollup + API report in git (for breaking change detection)
Both together → comprehensive library publishing setup

Methodology

Download data from npm registry (weekly average, February 2026). Feature comparison based on typedoc v0.26.x, jsdoc v4.x, and @microsoft/api-extractor v7.x.

Compare documentation and developer tool packages on PkgPulse →

Comments

Stay Updated

Get the latest package insights, npm trends, and tooling tips delivered to your inbox.