Generating API documentation for TypeScript packages with TypeDoc

; Date: Sat Mar 12 2022

Tags: Node.JS »»»» TypeScript

With TypeDoc, one adds structured comments (JSDoc style comments) to TypeScript source code. With data in those comments, TypeDoc generates nice API documentation you can easily publish to a website. With the addition of another tool, gh-pages, it is easy to publish the documentation to GitHub Pages.

It's important to publish the API to a package, showing the functions, method parameters, data types, and so on. Users of your API need to know what functions are available, and so forth. That helps them get up to speed, and to make use of your API. The more comprehensive the API documentation the better.

That makes it a best practice to publish good quality API documentation.

For most JavaScript packages, API documentation is unfortunately not comprehensive. As a user of many Node.js packages, I'm often frustrated at the sketchy API description. I imagine that the projects that lack good API documentation did not know about tools which simplify generating API documentation. I'm guilty of this myself in my own packages, and simply did not know of such tools. That left me generating API documentation by hand, which of course is not a best practice.

In this article we'll go over using TypeDoc to publish good quality API documentation for a TypeScript package.

I am writing this immediately after putting together a website, with API documentation, for my latest project. We'll be using this as a practical example.

JSDoc, TSDOC, and TypeDoc structured comments

One of the standard tools for JavaScript API documentation is JSDoc, but it doesn't support generating documentation for TypeScript code. The JSDoc approach uses structured comments like this:

/**
 * Description of the purpose or results of the function.
 * 
 * @param target Documentation for parameter 'target'
 * @param text   Documentation for parameter ´text´.
 * @return Comment about return value
 */
function doSomething(target: any, text: string): number {
    // code
}

These comments start with /** and end with */. In-between you can put free form text, that uses Markdown for formatting, as well as tags like @param for structured content.

TSDoc is a proposal for standard comment tags for use in TypeScript. It is not a tool for generating documentation, but a standard list of tags.

TypeDoc is a tool similar to JSDoc, but it supports TypeScript. It is an excellent tool for comprehensive documentation, which clearly lays out details like function parameters, return types, and more. It uses the same sort of structured comments as JSDoc, and supports a subset of the TSDoc/JSDoc comment tags.

The JSDoc-style comments used by TypeDoc follow a consistent structure that helps to clarify code structure, making the comments themselves a useful addition to your code. Further, IDE's like Visual Studio Code can display information from those comments in popups while editing the code.

Similar structured comments are used in many languages.

If you leave out the structured comments, the TypeScript compiler can deduce a lot of the information. But, by using the comments, you can add your own descriptions for an even better result.

Installing TypeDoc in a TypeScript project

Because both TypeScript and TypeDoc are Node.js tools, you must first have Node.js installed. Since the vast majority of folks reading this already know that, I'll assume you already have it installed. If not, read: Setting up the Typescript compiler to integrate with Node.js development

To start a blank TypeScript project:

$ npm init -y
$ npm install typescript @types/node --save-dev

You can now type this to see the usage instructions:

$ npx tsc --help

This verifies that TypeScript is installed and working.

The next step is a TypeScript configuration file, tsconfig.json. Since you're probably already a TypeScript programmer, you've probably already set up this configuration. A typical configuration is to store TypeScript source code in one directory, like src, and for TypeScript to build files into another directory, like dist or build.

To install TypeDoc run this command:

$ npm install typedoc --save-dev

This installs TypeDoc, saving it to the devDependencies.

Because TypeDoc generates a website, it's useful to have a local HTTP server so you can preview the documentation locally.

$ npm install @compodoc/live-server --save-dev

This particular server is very nice, includes live reloading when content changes, and other useful features.

Quick start for using TypeDoc in a TypeScript project

As a quick start experiment, run this command:

$ npx typedoc --out api src/index.ts
$ npm live-preview api

This command assumes your TypeScript source is in the src directory. It does not matter to TypeDoc what directory contains the built JavaScript code, since it reads the TypeScript sources.

This builds documentation into the api directory starting with a particular source file. Substitute here whichever source file is the main entry point for your package.

Default API documentation - Image by Author

This is the default API documentation generated for the (github.com) runtime-data-validation package.

The main section comes from the project README. The list of functions in the sidebar are the API. At the top is a couple sub-modules included in the package.

For this version, no customizations have been made to the documentation.

Typical documentation for an API method - Image by Author

This is the documentation for one of the functions in the package. That package is about data validation, and therefore this is about describing the parameters and results from one of the validation decorator functions.

Clearly this is good quality API documentation. The function parameters and results are clearly described in an organized manner. We have places to put our words. There is a link to the source code, which links directly to the GitHub repository.

But, on closer review of the result I found a number of things to change.

  • Navigation back to the main project website from the API documentation pages
  • Using text other than the project README
  • If on a documentation page, how to navigate back to the main API page
  • Having overview documentation of any submodules
  • TypeDoc does a poor job of presenting documentation of TypeScript decorators. The runtime-data-validation contains a long list of decorator functions, but the reader of the API does not know that these functions are decorator functions. I was unable to find a good solution for this issue.

TypeDoc offers a number of ways to customize the output, so lets take a look.

Configuring a TypeScript package to use TypeDoc

The most effective way to configure TypeDoc is with a configuration file. All of the options can be used on the command line, but that quickly gets to be very long.

Create a file named typedoc.json, which will contain the configuration. Start with this:

{
    "customTitle": "runtime-data-validation-js.github.io",
    "customTitleLink": "https://runtime-data-validation-js.github.io/",
    "name": "Runtime data validation for TypeScript",
    "includeVersion": true,
    "hideGenerator": true,
    "out": "api",
    "readme": "README-api.md",
    ...
}

The customTitle and customTitleLink properties govern the text at the very top of the page, and the link on that text. This link is to the home page for the runtime-data-validation project, which is a website generated using GitHub Pages. This ensures every page in the generated API documentation links back to the home page.

The name property is the page title on the home page of the API documentation. This text is a more user-friendly description of the project than the default chosen by TypeDoc. Using includeVersion adds the current version number, so that folks know what release they're looking at. Using hideGenerator hides the TypeDoc link at the bottom of the page.

The out property names the output directory.

The readme property overrides the default README used for the main page documentation. The project README already appears in the GitHub repository, and in the npmjs.com page. Why should folks read the same documentation for a third time. Why not instead use text here that is useful for someone reading the API documentation, such as advice on using the documentation.

This much gives some useful navigational improvements.

TypeDoc plugins and themes

TypeDoc offers two routes for deeper customization:

  • Themes override the default presentation of API documentation. For example one theme causes documentation to be output as Markdown files.
  • Plugins can make other changes

In the case of the runtime-data-validation project, I chose to not develop a custom theme, and only installed one plugin. The custom theme would have taken some time to get right, and the default theme is pretty good.

The one plugin I chose is typedoc-plugin-extras. It is what provides the customTitle and customTitleLink properties shown above.

For installation: npm install typedoc-plugin-extras --save-dev

To build API documentation between the config file and the plugin:

$ npx typedoc --plugin typedoc-plugin-extras --options typedoc.json ./src/index.ts

The --plugin option enables plugins, and --option uses the options file.

Useful documentation comments

While developing the API documentation for the runtime-data-validation project, I selected the following features of JSDoc/TypeDoc comments.

Categories let you organize the functions or other objects into groups. Category names are free-form in that you choose the category names which make sense to you.

/**
 * @category Finance Validator
 */

For example, the runtime-data-validation project contains a long list of data validation functions. This led to several categories for one type or another of validation functions.

Links to external documentation are enabled with the {@link} tag.

/**
 * check if the string is a valid RFC 3339 date.
 * {@link https://tools.ietf.org/html/rfc3339}
 * 
 * @param value The string to validate
 * @returns 
 * @category Date Validator
 */

This way users of your API can quickly go to the official documentation for something.

Links to internal types are also enabled with the {@link} tag.

/**
 * Check if the input is a valid ISO8601 date. 
 * 
 * @param value The string to validate
 * @param options {@link IsISO8601Options}
 * @returns 
 * @category Date Validator
 */

In this case, a separate type was defined to be used as a function parameter. This is a convenience link to that type.

Module comments let you give overview documentation of a group of functions or classes.

/**
 * Overview documentation for a module.
 * @module module-name
 */

The way this worked in the runtime-data-validation project is that there is a main module, and two sub-modules. In each sub-module directory there is an index.ts file exporting the API of that sub-module. At the top of index.ts is a comment structured like this:

/**
 * Overview documentation for a module.
 * 
 * [Return to home page](../index.html)
 * @module module-name
 */

The Markdown-style link just above the @module tag is a convenience link to the main API documentation page. This way readers of your API can more easily navigate around. For some reason TypeDoc does not include a link to the main page.

Publishing API documentation for public consumption

Of course the goal for this is to publish the API documentation in a place where folks can read it. Let's talk about some practical ways to do this. We'll use the method I used for (github.com) runtime-data-validation-js.github.io as an example.

Using the typedoc command we can generate a directory full of HTML, JavaScript and CSS files. But what is the best way to make a proper website using these files? Your answer is of course up to you. In my case, I have built a static website generator (AkashaCMS) and have an easy workflow for publishing websites to GitHub Pages using it. GitHub Pages is a feature of GitHub, where you can designate a branch in your repository to be shown as a website.

First, I created a GitHub Organization, (github.com) runtime-data-validation-js to house the project. The runtime-data-validation-js.github.io repository contains AkashaCMS code to generate a website which is visible at (runtime-data-validation-js.github.io) https://runtime-data-validation-js.github.io

The website contains documentation for using the package, as well as a blog. For the purpose of this discussion let's focus on the navigation bar:

This is the main navigation bar which shows on every page. The Search box uses DuckDuckGo as a site-specific search engine, for example. The (github.com) implementation of the navigation bar is a normal Bootstrap navbar. An important feature is the link named API, which is a link to the (runtime-data-validation-js.github.io) documentation as it is published using GitHub Pages. This means people reading the website have an easy way to get to the API documentation, just by clicking the API link.

The API documentation is generated by code in the (github.com) GitHub repository for the runtime-data-validation package. That's a normal every day GitHub repository for a TypeScript project. For this discussion, focus on the api directory where there is a sub-project dedicated to the task of generating API documentation. In that directory is a package.json, which contains scripts entries for driving the build and publishing process

"scripts": {
    "build": "npx typedoc --plugin typedoc-plugin-extras --options typedoc.json ../lib/index.ts",
    "publish": "npx gh-pages -b gh-pages -d site",
    "preview": "live-server site"
},

You see that build runs typedoc to build the HTML, and preview runs live-server for local preview. The build step references ../lib/index.ts as the entry point because that's where the file sits relative to the api directory.

The publish script uses gh-pages to publish to GitHub Pages. The (github.com) gh-pages tool is both an API for publishing to GitHub Pages, as well as a command-line tool. It takes care of everything required to get some HTML published using GitHub Pages.

In this case the API documentation is built into a directory named site. The -b gh-pages option means that the contents of the site directory is pushed into the gh-pages branch in the master repository.

As for the organization website, runtime-data-validation-js.github.io, gh-pages is used as well. In that case, AkashaCMS uses the gh-pages API to enable direct publishing to GitHub Pages.

Summary

It is very easy to use TypeDoc to build really nice API documentation for your TypeScript project.

With gh-pages it is very easy to publish that documentation to GitHub Pages.

About the Author(s)

(davidherron.com) David Herron : David Herron is a writer and software engineer focusing on the wise use of technology. He is especially interested in clean energy technologies like solar power, wind power, and electric cars. David worked for nearly 30 years in Silicon Valley on software ranging from electronic mail systems, to video streaming, to the Java programming language, and has published several books on Node.js programming and electric vehicles.

Books by David Herron

(Sponsored)