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:
> npm init -y
For this blog I've created a small app (download code) containing 3 files:
- src/app.js
- src/models/user.mjs
- src/models/todo.mjs
Then update the package.json
file to use ES Modules:
{
"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
// 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.
// 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.
// 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:
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:
-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.
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.
This is where JSDoc 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:
/**
*
*/
Inside you can describe your classes, interfaces, functions, their properties, and return types however you like:
/**
* 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.
This is also applied to the methods that you document:
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
> tsc -init
Now paste the following config into the newly generated tsconfig.json
file:
{
"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
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
/**
* 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:
> npm i -D ts-node
Now add ts-node
to the start
script in the package.json
file:
{
"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 using npm:
> npm i typedoc -D
Then update the tsconfig.json
file with Typedoc configuration:
{
"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
"scripts": {
"start": "ts-node ./src/app.ts",
"type-docs": "typedoc" // <-- reads config from tsconfig.json
},
Run the script using:
> 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.
More complex projects will have better-detailed docs.
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 and follow me on Twitter to stay up to date with my content updates.
Bye for now 👋
Top comments (3)
One of my favorite tricks is using markdown in JSDoc comments, as it is supported by virtually all IDEs and editors with JSDoc support.
Really? I haven't tried that. Thanks for the input
The typescript one is awesome 😍😍😍