@microsoft/api-extractor vs dts-generator vs tsd vs typedoc
Generating and Managing TypeScript Declaration Files and API Documentation
@microsoft/api-extractordts-generatortsdtypedocSimilar Packages:

Generating and Managing TypeScript Declaration Files and API Documentation

@microsoft/api-extractor, dts-generator, tsd, and typedoc address different stages of the TypeScript library lifecycle. @microsoft/api-extractor is an enterprise-grade tool for rolling up .d.ts files, validating API surfaces, and generating strict documentation. dts-generator is a legacy utility for concatenating declaration files, largely superseded by native TypeScript features. tsd is a testing framework specifically for asserting the types of .d.ts files, not for generating them. typedoc is a documentation generator that converts TypeScript source comments into static HTML sites, similar to JSDoc but with type awareness.

Npm Package Weekly Downloads Trend

3 Years

Github Stars Ranking

Stat Detail

Package
Downloads
Stars
Size
Issues
Publish
License
@microsoft/api-extractor06,4913.49 MB1,086a day agoMIT
dts-generator0515-378 years agoBSD-3-Clause
tsd02,55694.9 kB54a year agoMIT
typedoc08,4452.18 MB172 months agoApache-2.0

TypeScript Tooling Showdown: API Extractor, TSD, TypeDoc, and the Legacy Generator

When building and maintaining TypeScript libraries, developers often face a confusing array of tools for handling declaration files (.d.ts) and documentation. While the TypeScript compiler (tsc) handles the basics, professional workflows often require specialized tools to bundle declarations, test type safety, or generate rich documentation. Let's break down @microsoft/api-extractor, dts-generator, tsd, and typedoc to see where each fits in a modern architecture.

πŸ“¦ Bundling Declarations: Rolling Up vs. Concatenating

One of the most common pain points in library development is managing multiple internal .d.ts files. Consumers usually prefer a single entry point. This is where @microsoft/api-extractor and the legacy dts-generator differ significantly.

@microsoft/api-extractor analyzes your compiled output and rolls up all declarations into a single .d.ts file. It also trims unused exports based on your configuration, ensuring a clean public API.

// api-extractor.json configuration
{
  "mainEntryPointFilePath": "<projectFolder>/lib/index.d.ts",
  "bundledPackages": [],
  "compiler": {
    "tsconfigFilePath": "<projectFolder>/tsconfig.json"
  },
  "apiReport": {
    "enabled": true
  },
  "dtsRollup": {
    "enabled": true,
    "untrimmedFilePath": "<projectFolder>/dist/my-lib.d.ts"
  }
}

dts-generator was an early solution that simply concatenated files in a specific order. It lacks the semantic understanding of the code that api-extractor has and does not handle trimming or API validation.

# dts-generator: CLI usage (Legacy)
# Concatenates all .d.ts files from src into dist/index.d.ts
dts-generator --out dist/index.d.ts --name my-lib --src src/**/*.d.ts

tsd does not bundle files. It focuses purely on testing the resulting types.

// tsd: No bundling capability
// This tool is used in a test file to assert types, not to create output files
import { expectType } from 'tsd';
// ... assertions here

typedoc also does not bundle declaration files for distribution. It reads them to generate documentation but leaves the build artifacts untouched.

# typedoc: Generates HTML, not .d.ts bundles
typedoc --out docs ./src/index.ts

πŸ§ͺ Testing Types: The Role of TSD

While other tools focus on building or documenting, tsd fills a critical gap: verifying that your types actually work as intended for the end user.

tsd allows you to write tests that assert types without running any JavaScript. If the types change in a breaking way, the test fails.

// __tests__/index.test-d.ts
import { expectType, expectError } from 'tsd';
import { MyFunction } from '../dist';

// Asserts that MyFunction returns a string
expectType<string>(MyFunction('input'));

// Asserts that passing a number causes a type error
expectError(MyFunction(123));

@microsoft/api-extractor performs a different kind of validation. It checks your API surface against a stored "signature" file to ensure you haven't accidentally changed public contracts.

# api-extractor: Validates API surface against a baseline
npx api-extractor run --local

# If you changed a public method signature, this command fails
# and prompts you to update the .api.md report file.

dts-generator has no testing capabilities. It is purely a file manipulation tool.

# dts-generator: No test command exists
# Usage is limited to file generation only

typedoc does not test types. However, if your types are invalid, TypeDoc may fail to parse the source files, acting as a passive sanity check.

# typedoc: Fails if source has syntax errors, but doesn't assert logic
typedoc --skipErrorChecking false ./src

πŸ“š Documentation Generation: Static Sites vs. API Reports

Documentation needs vary by project. Some teams need a full website; others need a strict changelog of API changes.

typedoc excels at creating beautiful, navigable HTML documentation sites from JSDoc comments and TypeScript types.

# typedoc: Generate a full HTML site
typedoc --out ./docs --entryPointStrategy expand ./src

// Result: A folder of HTML files with search, hierarchy, and code highlighting

@microsoft/api-extractor generates a Markdown API report (.api.md). This isn't a website for users, but a precise contract for maintainers to review changes.

// Output: temp/my-lib.api.md (Generated by api-extractor)
## Functions

### myFunction

> Signature: `myFunction(input: string): string`
>
> Remarks:
> Performs a specific operation on the input string.

dts-generator does not generate documentation. It only produces a combined .d.ts file which serves as raw data for IDEs, not human-readable docs.

// dts-generator output: A raw .d.ts file
// Not suitable for direct human reading as documentation
declare module 'my-lib' {
  export function myFunction(input: string): string;
}

tsd does not generate documentation. Its output is strictly pass/fail test results in the terminal.

# tsd output: Terminal test results
# βœ”  index.test-d.ts
# βœ–  index.test-d.ts (if types mismatch)

⚠️ Deprecation Warning: The Case Against dts-generator

It is crucial to note that dts-generator is effectively deprecated for modern workflows. Before TypeScript 2.0, developers needed external tools to combine declaration files. Today, the TypeScript compiler supports declarationMap and modern bundlers (like Rollup or Vite) can handle .d.ts files natively. More importantly, @microsoft/api-extractor provides a superior, semantically aware alternative for rolling up types.

// Modern Alternative: Using TypeScript native features + api-extractor
// tsconfig.json
{
  "compilerOptions": {
    "declaration": true,
    "declarationMap": true // Native source mapping for .d.ts
  }
}

// Then use api-extractor for the final rollup, avoiding dts-generator entirely.

Using dts-generator in a new project introduces technical debt and removes the safety checks provided by newer tools.

🌐 Real-World Scenarios

Scenario 1: Publishing a New UI Library to NPM

You are building a component library and want to ensure consumers get a single type definition file and that you don't break APIs accidentally.

  • βœ… Best choice: @microsoft/api-extractor
  • Why? It bundles your types, trims internal APIs, and enforces a strict API contract via the .api.md report.
// package.json script
"scripts": {
  "build": "tsc && api-extractor run --local"
}

Scenario 2: Verifying Types for a Utility Package

You maintain a low-level utility package and need to guarantee that your types support both string and number inputs without writing runtime tests.

  • βœ… Best choice: tsd
  • Why? It allows you to codify type expectations as test cases that run in CI.
// __tests__/utils.test-d.ts
import { expectType } from 'tsd';
expectType<number | string>(myUtil(1));
expectType<number | string>(myUtil('a'));

Scenario 3: Creating Developer Documentation for an Internal Tool

Your team needs a searchable website to understand how to use the internal design system.

  • βœ… Best choice: typedoc
  • Why? It generates a static site with navigation, search, and examples directly from code comments.
# Command to generate docs for the team wiki
typedoc --out ./wiki-src --theme default ./src/components

Scenario 4: Legacy Migration

You are maintaining an old library that uses dts-generator to merge files.

  • βœ… Best choice: Migrate to @microsoft/api-extractor
  • Why? dts-generator is obsolete. Moving to api-extractor improves reliability and adds API validation.
// Migration step: Replace dts-generator call in build script
// OLD: dts-generator --out dist/index.d.ts ...
// NEW: api-extractor run

πŸ“Œ Summary Table

Feature@microsoft/api-extractordts-generatortsdtypedoc
Primary GoalBundle & Validate APIConcatenate Files (Legacy)Test TypesGenerate HTML Docs
Output Format.d.ts bundle, .api.md.d.ts bundleCLI Pass/FailHTML Website
API Validationβœ… Strict contract checking❌ None⚠️ Type structure only❌ None
Status🟒 Active / Industry StandardπŸ”΄ Deprecated / Legacy🟒 Active🟒 Active
Best ForLibrary PublishersNone (Migrate away)Type Test AuthorsDoc Site Maintainers

πŸ’‘ Final Recommendation

For professional TypeScript development, your toolkit should look like this:

  1. Use @microsoft/api-extractor for your build pipeline. It is the only robust solution for bundling declarations and enforcing API stability in published packages.
  2. Use tsd in your test suite. It ensures your types remain correct and backward-compatible without bloating your runtime code.
  3. Use typedoc if you need a public-facing documentation website. It complements api-extractor by providing the human-readable layer on top of your strict API definitions.
  4. Avoid dts-generator. It solves a problem that modern TypeScript and api-extractor have already solved better. Removing it simplifies your dependency tree and reduces risk.

By combining these tools, you create a workflow that not only builds code but also guarantees the quality and usability of your types for every consumer.

How to Choose: @microsoft/api-extractor vs dts-generator vs tsd vs typedoc

  • @microsoft/api-extractor:

    Choose this if you are publishing a professional TypeScript library to npm and need to bundle multiple .d.ts files into a single entry point, enforce API stability rules, and generate strict API reports. It is the industry standard for library authors who need control over their public surface area and want to prevent accidental breaking changes.

  • dts-generator:

    Avoid this package for new projects. It was designed to concatenate declaration files before TypeScript 2.0 introduced native declarationMap and bundling capabilities. Using it today adds unnecessary complexity and maintenance overhead when the TypeScript compiler (tsc) or api-extractor can handle these tasks more reliably.

  • tsd:

    Choose tsd if you need to write unit tests specifically for your TypeScript definition files (.d.ts). It is essential for library authors who want to verify that their types work correctly for consumers without writing implementation code. Do not use it for generating documentation or bundling declarations.

  • typedoc:

    Choose typedoc if your primary goal is to generate a browsable HTML documentation website from your TypeScript source code and JSDoc comments. It is ideal for creating public-facing docs for internal tools or open-source libraries, but it does not bundle .d.ts files or enforce API contracts like api-extractor does.

README for @microsoft/api-extractor

@microsoft/api-extractor

API Extractor
Β Β Β Β Β  https://api-extractor.com/

API Extractor helps you build better TypeScript library packages. Suppose for example that your company has published an NPM package called "awesome-widgets" that exports many classes and interfaces. As developers start to depend on your library, you may encounter issues such as...

  • Accidental breaks: People keep reporting that their code won't compile after a supposedly "minor" update. To address this, you boldly propose that every awesome-widgets pull request must be approved by an experienced developer from your team. But that proves unrealistic -- nobody has time to look at every single PR! What you really need is a way to detect PRs that change API contracts, and flag them for review. That would focus attention in the right place... but how to do that?

  • Missing exports: Suppose the awesome-widgets package exports an API function AwesomeButton.draw() that requires a parameter of type DrawStyle, but you forgot to export this enum. Things seem fine at first, but when a developer tries to call that function, they discover that there's no way to specify the DrawStyle. How to avoid these oversights?

  • Accidental exports: You meant for your DrawHelper class to be kept internal, but one day you realize it's being exported. When you try to remove it, consumers complain that they're using it. How do we avoid this in the future?

  • Alpha/Beta graduation: You want to release previews of new APIs that are not ready for prime time yet. But if you did a major SemVer bump every time these definitions evolve, the villagers would be after you with torches and pitchforks! A better approach is to designate certain classes/members as alpha quality, then promote them to beta and finally to public as they mature. But how to indicate this to your consumers? (And how to detect scoping mistakes? A public function should never return a beta result.)

  • *.d.ts rollup: You webpacked your library into a nice *.js bundle file -- so why ship your typings as a messy tree of lib/*.d.ts files full of private definitions? Can't we consolidate them into a tidy *.d.ts rollup file? And if you publish internal/beta/public releases, each release type should get its own *.d.ts file with appropriate trimming. Developers building a production project don't want to see a bunch of internal and beta members in their VS Code IntelliSense!

  • Online documentation: You have faithfully annotated each TypeScript member with nice TSDoc descriptions. Now that your library has shipped, it's time to set up a nicely formatted API reference. What tool to use?

API Extractor provides an integrated, professional-quality solution for all these problems. It is invoked at build time by your toolchain and leverages the TypeScript compiler engine to:

  • Detect a project's exported API surface
  • Capture the contracts in a concise report designed to facilitate review
  • Warn about common mistakes (e.g. missing exports, inconsistent visibility, etc.)
  • Generate *.d.ts rollups with trimming according to release type
  • Output API documentation in a portable format that's easy to integrate with your content pipeline

Best of all, API Extractor is free and open source. Join the community and create a pull request!

Getting Started

For more details and support resources, please visit: https://api-extractor.com/

Links

API Extractor is part of the Rush Stack family of projects.