Documenting JavaScript code with JSDoc
Tags: javascript, jsdoc
Published: 2022-11-24 18:49:15

---
title: Documenting JavaScript code with JSDoc
date: 2022-11-24 18:49:00 UTC
published: true
tags: ['javascript', 'jsdoc']
canonical_url: https://sevic.dev/notes/javascript-jsdoc/
---

JSDoc provides adding types to the JavaScript codebase with appropriate conventions inside comments so different IDEs like Visual Studio Code can recognize defined types, show them and make coding easier with auto-completion. Definitions are put inside `/** */` comments.

### Examples

Custom types can be defined with `@typedef` and `@property` tags. Every property has a type and if the property is optional, its name is put between square brackets, and a description can be included after the property name. Global types should be defined in `*.jsdoc.js` files so they can be used in multiple files without importing. `*` represents any type.

```js
/**
 * @typedef {object} CollectionItem
 * @property {string} [collectionName] - collection name is optional string field
 * @property {boolean} isRevealed - reveal status
 * @property {number} floorPrice - floor price
 * @property {?string} username - username is a nullable field
 * @property {Array.<number>} prices - prices array
 * @property {Array.<string>} [buyers] - optional buyers array
 * @property {Array.<Object<string, *>>} data - some data
 */
```

Classes are auto recognized so `@class` and `@constructor` tags can be omitted.

```js
/**
 * Scraper for websites
 */
class Scraper {
  /**
   * Create scraper
   * @param {string} url - website's URL
   */
  constructor(url) {
    this.url = url;
  }
  // ...
}
```

Comments starting with the description can omit `@description` tag. Function parameters and function return types can be defined with `@param` and `@returns` tags. Multiple return types can be handled with `|` operator. Deprecated parts of the codebase can be annotated with `@deprecated` tag.

```js
/**
 * Gets prices list
 * @private
 * @param {Array.<number>} prices - prices array
 * @returns {string|undefined}
 */
const getPricesList = (prices) => {
  if (prices.length > 0) return prices.join(',');
};

/**
 * Get data from the API
 * @deprecated
 * @returns {Promise<CollectionItem>}
*/
const getData = async () => {
  // ...
};
```

Variable types can be documented with `@type` tags and constants can utilize `@const` tags.

```js
/**
 * Counter for the requests
 * @type {number}
 */
let counter;

/**
 * HTTP timeout in milliseconds
 * @const {number}
*/
const HTTP_TIMEOUT_MS = 3000;
```

Enums can be documented with `@enum` and `@readonly` tags.

```js
/**
 * Some states
 * @readonly
 * @enum {string}
 */
const state = {
  STARTED: 'STARTED',
  IN_PROGRESS: 'IN_PROGRESS',
  FINISHED: 'FINISHED',
};
```

### Docs validation

Linter can validate the docs. Add the following package and update the linter configuration file.

```bash
npm i -D eslint-plugin-jsdoc
```

```js
// .eslintrc.js
module.exports = {
  extends: ['plugin:jsdoc/recommended'],
};
```

Run the linter and it will show warnings if something has to be improved.

### Generating the docs overview

Run the following command to recursively generate the HTML files with the docs overview, including the README.md and package.json content. Symbols marked with `@private` tags will be skipped.

```bash
npx jsdoc src -r --destination docs --readme ./README.md --package ./package.json
```

This command can be included in the CI/CD pipeline, it depends on the needs of the project.

### Boilerplate

Here is the [link](https://sevic.dev/nestjs-starter?ref=devto-jsdoc) to the boilerplate I use for the development.