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.
-
https://runtime-data-validation-js.github.io/ -- the
runtime-data-validation
package is a set of TypeScript decorators for enforcing data validity - https://runtime-data-validation-js.github.io/runtime-data-validation-typescript/ -- Is the API documentation for this package
-
https://github.com/runtime-data-validation-js/runtime-data-validation-typescript -- Package source code. Look in the
api
directory for the process to build the API site. - https://github.com/runtime-data-validation-js/runtime-data-validation-js.github.io -- Website source code.
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.
This is the default API documentation generated for the
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.
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
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,
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
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
implementation of the navigation bar is a normal Bootstrap navbar. An important feature is the link named API
, which is a link to the
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 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
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.