Learn how to document JavaScript/TypeScript code using JSDoc & Typedoc
Tags: javascript, typescript, typedoc
Published: 2024-03-03 00:48:49

---
title: Learn how to document JavaScript/TypeScript code using JSDoc & Typedoc
published: true
description: 
tags: javascript, typescript, typedoc
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xnx31lfni5mz3omn4jre.png
# Use a ratio of 100:42 for best results.
# published_at: 2024-03-02 22:18 +0000
---

In this blog, you'll learn how to document your JS/TS code, how to give more context to your functionalities using JSDoc, and how to generate documentation files using Typedoc.

## Setting up the project

Create a new project using npm:

```bash
> npm init -y
```

For this blog I've created a small app ([download code](https://gist.github.com/MirzaLeka/a96ae0d71802c272317c46f4e5f49ae6)) containing 3 files:

* src/app.js
* src/models/user.mjs
* src/models/todo.mjs

Then update the `package.json` file to use ES Modules:

```json
{
  "name": "js-docs",
  "version": "1.0.0",
  "description": "",
  "main": "app.js",
  "type": "module", // <--- this part
  "scripts": {
    "start": "node ./src/app.js",
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}
```

### Basic Todo class

```js
// todo.mjs
export default class Todo {
  id;
  title;
  description;
  isCompleted;

  constructor(id, title, description, isCompleted) {
    this.id = id;
    this.title = title;
    this.description = description;
    this.isCompleted = isCompleted;
  }
}
```


### Basic User class
A user holds a list of Todos.

```js
// user.mjs
export default class User {
  id;
  username;
  #todos = []; // #todos is a private class member

  constructor(id, username) {
    this.id = id;
    this.username = username;
  }

  addTodo(todo) {
    this.#todos.push(todo);
  }

  getTodos() {
    return this.#todos;
  }
}
```

Now let's put them together. 
Back in app.js create an instance of user, followed by an instance of todo.

```js
// app.js
import Todo from './models/todo.mjs';
import User from './models/user.mjs';

const todo = new Todo(1, 'Must write a new blog', 'Something awesome', false);
const user = new User(1, 'Mirzly');
```

Now assign this todo to a user:

```js
import Todo from './models/todo.mjs';
import User from './models/user.mjs';

const todo = new Todo(1, 'Must write a new blog', 'Something awesome', false);
const user = new User(1, 'Mirzly');

user.addTodo(todo);
const userTodos = user.getTodos();

console.log('userTodos :>> ', userTodos);
```

If you run the app (using `npm start`), you should see user todos printed in the console:

```bash
-docs>npm start

> js-docs@1.0.0 start
> node ./src/app.js

userTodos :>>  [
  Todo {
    id: 1,
    title: 'Must write a new blog',
    description: 'Something awesome',
    isCompleted: false
  }
]
```

## Adding Docs
If you hover over the Todo or User class, there is very little information about either class.

![User-hover](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lpjw3chj2wmpqvp7fp4b.png)

And since JavaScript doesn't have type safety, there is no IntelliSense to tell you what methods are available on the object and what parameters you can pass to them.

![no-IntelliSense](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mk643p4wfiy4salkj2uo.png)

This is where [JSDoc](https://jsdoc.app/) comes to save the day.

In JavaScript, you can generate docs by simply typing `/**` and hitting enter. The Visual Studio Code then sets up a wrapper:

```js
/**
 * 
 */
```

Inside you can describe your classes, interfaces, functions, their properties, and return types however you like:

```js
/**
 * Creates a new User
 * @property {number} id - User Id
 * @property {string} username - User username
 * @method addTodo {Function} - Adds new todo
 * @method getTodos {Function} - Retrieves all todos
 */
export default class User { 
  // ...

  /**
   * Used to add a new todo
   * @param {Todo} todo - New todo
   * @returns {void} - Does not return anything
   */
  addTodo(todo): void {
    this.#todos.push(todo);
  }

  /**
   * Used to retrieve all todos
   * @returns {Todo[]} - Todos list
   */
  getTodos() {
    return this.#todos;
  }

}

```

Now if you hover over the User class you should see more info.


![user-with-docs](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y9sxqn367q5jejvgx680.png)

This is also applied to the methods that you document:

![method-docs](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cekvrf965b30f0srevh3.png)

How cool is that?

## TypeDoc
Now let's add TypeDoc - Documentation generator for TypeScript.
That said, you need to initialize a TypeScript project:

### Setting up TypeScript

```bash
> tsc -init
```
Now paste the following config into the newly generated `tsconfig.json` file:

```json
{
  "compilerOptions": {
    "target": "es2016",
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,
    "module": "commonjs",
    "outDir": "./dist",
    "esModuleInterop": true,
    "resolveJsonModule": true,
    "forceConsistentCasingInFileNames": true,
    "strict": true,
    "skipLibCheck": true
  }
}
```

### Changing file structure

Now rename all your `.js`/`.mjs` files to `.ts`:
* src/app.ts
* src/models/user.ts
* src/models/todo.ts

Also be sure to remove the `"type": "module"` from the `package.json` file as that can confuse Node.js when running the files.

### Fixing formatting

TypeScript will complain about the lack of "types" in the files. Here are the changed files:

#### user.ts

```ts
import Todo from './todo';

/**
 * Creates a new User
 * @property {number} id - User Id
 * @property {string} username - User username
 * @method addTodo {Function} - Adds new todo
 * @method getTodos {Function} - Retrieves all todos
 */
export default class User {
  id: number;
  username: string;
  #todos: Todo[] = [];

  constructor(id: number, username: string) {
    this.id = id;
    this.username = username;
  }

  /**
   * Used to add a new todo
   * @param {Todo} todo - New todo
   * @returns {void} - Does not return anything
   */
  addTodo(todo: Todo): void {
    this.#todos.push(todo);
  }

  /**
   * Used to retrieve all todos
   * @returns {Todo[]} - Todos list
   */
  getTodos(): Todo[] {
    return this.#todos;
  }
}

```

#### todo.ts 

```ts
/**
 * Creates a new Todo
 * @property {number} id - Todo id
 * @property {string} title - Todo title
 * @property {string} description - Todo description
 * @property {boolean} isCompleted - Todo isCompleted status
 */
export default class Todo {
  id: number;
  title: string;
  description: string;
  isCompleted: boolean;

  constructor(id: number, title: string, description: string, isCompleted: boolean) {
    this.id = id;
    this.title = title;
    this.description = description;
    this.isCompleted = isCompleted;
  }
}

```

### Running the app (TS)

You need to install `ts-node` to run the Typescript files:

```bash
> npm i -D ts-node
```

Now add `ts-node` to the `start` script in the `package.json` file:

```json
{
  "name": "js-docs",
  "version": "1.0.0",
  "description": "",
  "scripts": {
    "start": "ts-node ./src/app.ts"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "ts-node": "^10.9.2"
  }
}
```
Running the app using `npm start` should print the same result as before.

## Adding TypeDoc

Firstly, install [Typedoc](https://typedoc.org/) using npm:

```bash
> npm i typedoc -D
```
Then update the `tsconfig.json` file with Typedoc configuration:

```json
{
  "compilerOptions": {...},
  "typedocOptions": {
    "entryPoints": [
      "src/models/*.ts" // <--- take everything from this location
    ],
    "out": "docs/typedoc" // <--- output directory
  }
}
```
Lastly, add a script that is used from running Typedoc

```json
  "scripts": {
    "start": "ts-node ./src/app.ts",
    "type-docs": "typedoc" // <-- reads config from tsconfig.json
  },
```

Run the script using:

```bash
> npm run type-docs

[info] Documentation generated at ./docs/typedoc
```
This will generate HTML docs page in the specified path (`"out": "docs/typedoc"`) that you can open in your web browser.


![docs-preview1](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ecpz2f4n0bi428vb7dbd.png)

![docs-preview2](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8xw8x09alybxo8dcmmym.png)

More complex projects will have better-detailed docs.

![docs-preview3](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f2wzq5zbd4rlptuoasph.png)

That's all from me today. 
If you'd like to learn more make sure to check out my other blog as well on [Medium](https://mirzaleka.medium.com) and follow me on [Twitter](https://twitter.com/mirzaleka) to stay up to date with my content updates.

Bye for now 👋