🌱 Growing Every Day — Early access. New content drops regularly!

content

JS Docs

Description

Learning Outcomes

By the end of this lesson, you will be able to:

  • 1Explain the purpose and benefits of JSDocs for code documentation
  • 2Write JSDoc comments with descriptions for functions and React components
  • 3Document function parameters using @param with appropriate data types
  • 4Document return values using @returns with types and descriptions
  • 5Create usage examples using @example with syntax-highlighted code blocks
  • 6Document optional parameters and default values using square bracket notation
  • 7Define custom reusable types using @typedef
  • 8Document complex object parameters using dot notation or inline destructuring
  • 9Document React component props including event handlers and children
  • 10Generate HTML documentation for a project using the JSDoc CLI tool

Introduction

Imagine you've written a function three months ago. You come back to use it and can't remember what parameters it needs or what it returns. You have to dig through the code to figure it out. Now imagine your teammate needs to use your function—they have the same problem, but they also can't ask you because you're on holiday.

JSDocs solves this problem. It's a standardized way to document your code that:

  1. Gives developers information about your code when they hover over it in VS Code
  2. Enables TypeScript-style type checking without writing TypeScript
  3. Can automatically generate documentation websites for your projects

By the end of this lesson, you'll be able to document any function professionally.


How to Use JSDocs

JSDocs works by adding information between special opening and closing comment tags: /** */. This comment block goes directly above a function.

NOTE: Any lines between the /** and */ tags need to have a * at the front. VS Code will automatically insert this for you when you press Enter while your cursor is inside a JSDoc comment.

Let's start with simple examples—a regular JavaScript function.

TIP: JSDocs is smart and will detect your function's parameters and return value. It's best to add JSDocs after you've finished writing the function so you can take advantage of this autocompletion.

Normal JS Function

/**
* Adds two numbers together
*/
export function addNumbers(a, b) {
return a + b;
}

When you hover over either of these in VS Code, you'll see a tooltip containing the description from the JSDoc comment:

[Image: Screenshot showing VS Code tooltip displaying JSDoc description "Adds two numbers together" when hovering over the addNumbers function]

This is incredibly useful for other developers (including future you) who want to use your functions and components without reading through all the code.


Common Data Types for JSDocs

Before we go further, here are the data types you'll use most often:

TypeDescriptionExample Values
stringText"hello", 'world'
numberNumbers (integers and decimals)42, 3.14
booleanTrue or falsetrue, false
ObjectAny object{ name: "John" }
ArrayAny array[1, 2, 3]
Array<string>Array of strings["a", "b", "c"]
Array<number>Array of numbers[1, 2, 3]
FunctionAny function() => {}
nullNull valuenull
undefinedUndefined valueundefined
*Any type (avoid when possible)anything

Union Types

You can specify that a parameter accepts multiple types using the pipe | symbol:

/**
* Displays a message to the user
* @param {string|number} id The user ID (can be string or number)
*/
function getUser(id) {
// ...
}

Nullable Types

Use ? before the type to indicate a value can be null:

/**
* Finds a user by email
* @param {string} email The email to search for
* @returns {?Object} The user object, or null if not found
*/
function findUserByEmail(email) {
// ...
}

@param

The @param tag documents your function's parameters, including their types and descriptions. This is essential for helping other developers understand what values to pass in.

NOTE: TypeScript can automatically convert JSDocs types to TypeScript types. If you see a white squiggle under a function name with the message JSDoc types may be moved to TypeScript types, you can use Quick Fix to select Annotate with type from JSDoc for automatic conversion.

Syntax

/**
* Example function
* @param {dataType} parameterName Parameter description
*/
  • dataType: The data type of the parameter (e.g., string, number)
  • parameterName: The exact name of the parameter as it appears in your function
  • Parameter description: A brief explanation of what this parameter is for

Practical Example

Let's add @param tags to our addNumbers function:

/**
* Adds two numbers together
* @param {number} a First value to add
* @param {number} b Second value to add
*/
export function addNumbers(a, b) {
return a + b;
}

@returns

The @returns tag documents what your function returns, including the data type and a description.

Syntax

/**
* Example function
* @returns {dataType} Description of the return value
*/

Practical Example

Let's extend our addNumbers function to include @returns:

/**
* Adds two numbers together
* @param {number} a First value to add
* @param {number} b Second value to add
* @returns {number} The sum of both parameters
*/
export function addNumbers(a, b) {
return a + b;
}

@example

The @example tag is one of the most valuable additions to your documentation. It shows other developers exactly how to use your function with real code. When done well, it looks professional and saves time.

The @example tag uses Markdown syntax, which means you can add syntax-highlighted code blocks.

Adding Syntax Highlighting with Markdown

You can wrap your code in triple backticks with a language identifier:

```js
console.log('Hello world');
```

You can use js for JavaScript, jsx for React, ts for TypeScript, and tsx for React TypeScript.

Practical Example

Let's add an @example to our addNumbers function:

/**
* Adds two numbers together
* @param {number} a First value to add
* @param {number} b Second value to add
* @returns {number} The sum of both parameters
* @example
* ```js
* const a = 1;
* const b = 2;
* const sum = addNumbers(a, b);
* console.log(sum); // 3
* ```
*/
export function addNumbers(a, b) {
return a + b;
}

Your tooltip will now show everything—types, descriptions, and a working example:

[Image: Screenshot showing VS Code tooltip with full JSDoc documentation including function signature with types, description, @param details, @returns, and @example code block with syntax highlighting]


Optional Parameters

You can mark a parameter as optional by wrapping its name in square brackets [ ].

Syntax

/**
* Example function
* @param {dataType} [optionalParameterName] Description of optional parameter
*/

This is equivalent to TypeScript's optional property syntax:

type MyType = {
optionalParameterName?: dataType;
};

Practical Example

/**
* Adds two numbers together
* @param {number} a First value to add
* @param {number} [b] Second value to add (optional)
* @returns {number} The sum of both parameters
*/
export function addNumbers(a, b = 10) {
return a + b;
}

Default Values

You can also document the default value using = inside the brackets:

/**
* Adds two numbers together
* @param {number} a First value to add
* @param {number} [b=10] Second value to add (defaults to 10)
* @returns {number} The sum of both parameters
*/
export function addNumbers(a, b = 10) {
return a + b;
}

@typedef

@typedef lets you define custom types that you can reuse throughout your code. This is similar to creating a type or interface in TypeScript.

TIP: Define your @typedef blocks at the top of your file or in a separate types file to keep your code organized.

Syntax

/**
* Description of the type
* @typedef {baseType} TypeName
*/

Practical Example

/**
* A value that can be either a number or a string containing a number
* @typedef {number|string} NumberLike
*/
/**
* Adds two number-like values together
* @param {NumberLike} a First value
* @param {NumberLike} b Second value
* @returns {number} The sum of both values
*/
export function addNumbers(a, b) {
return Number(a) + Number(b);
}

Complex Objects

Functions often accept objects with multiple properties. There are three ways to document these in JSDocs.

Option 1: Inline Destructuring

Best for simple objects with few properties:

/**
* Creates a greeting message
* @param {{name: string, age: number}} person The person to greet
* @returns {string} A personalized greeting
*/
function greet(person) {
return `Hello ${person.name}, you are ${person.age} years old!`;
}

Option 2: Dot Notation

Best for documenting each property with detailed descriptions:

/**
* Creates a greeting message
* @param {Object} person The person to greet
* @param {string} person.name The person's full name
* @param {number} person.age The person's age in years
* @returns {string} A personalized greeting
*/
function greet(person) {
return `Hello ${person.name}, you are ${person.age} years old!`;
}

Option 3: Using @typedef

Best for reusable types used across multiple functions:

/**
* Represents a person
* @typedef {Object} Person
* @property {string} name The person's full name
* @property {number} age The person's age in years
*/
/**
* Creates a greeting message
* @param {Person} person The person to greet
* @returns {string} A personalized greeting
*/
function greet(person) {
return `Hello ${person.name}, you are ${person.age} years old!`;
}

JSDocs for React Components

React components benefit greatly from JSDocs because they clearly document props. Let's look at progressively more complex examples.

Basic Component with Props

/**
* Displays a greeting message to a user
* @param {Object} props Component props
* @param {string} props.name The user's name to greet
*/
export default function Greeting({ name }) {
return <div>Hello, {name}!</div>;
}

Component with Multiple Props and Events

/**
* A reusable button component with loading state
* @param {Object} props Component props
* @param {string} props.label The button text
* @param {boolean} [props.isLoading=false] Whether the button shows a loading state
* @param {boolean} [props.disabled=false] Whether the button is disabled
* @param {'primary'|'secondary'|'danger'} [props.variant='primary'] The button style variant
* @param {Function} props.onClick Click handler function
* @example
* ```jsx
* <Button
* label="Save Changes"
* variant="primary"
* isLoading={isSaving}
* onClick={handleSave}
* />
* ```
*/
export default function Button({
label,
isLoading = false,
disabled = false,
variant = "primary",
onClick,
}) {
return (
<button
className={`btn btn-${variant}`}
disabled={disabled || isLoading}
onClick={onClick}
>
{isLoading ? "Loading..." : label}
</button>
);
}

Using @typedef for Props (Cleaner Approach)

For components with many props, define a type first:

/**
* Props for the ProductCard component
* @typedef {Object} ProductCardProps
* @property {string} title The product title
* @property {number} price The price in dollars
* @property {string} imageUrl URL to the product image
* @property {boolean} [inStock=true] Whether the product is in stock
* @property {Function} onAddToCart Callback when add to cart is clicked
*/
/**
* Displays a product card with image, price, and add to cart button
* @param {ProductCardProps} props Component props
* @example
* ```jsx
* <ProductCard
* title="Wireless Headphones"
* price={79.99}
* imageUrl="/images/headphones.jpg"
* onAddToCart={() => addToCart(productId)}
* />
* ```
*/
export default function ProductCard({
title,
price,
imageUrl,
inStock = true,
onAddToCart,
}) {
return (
<div className="product-card">
<img src={imageUrl} alt={title} />
<h3>{title}</h3>
<p>${price.toFixed(2)}</p>
{inStock ? (
<button onClick={onAddToCart}>Add to Cart</button>
) : (
<span className="out-of-stock">Out of Stock</span>
)}
</div>
);
}

Documenting Children Props

/**
* A card wrapper component that provides consistent styling
* @param {Object} props Component props
* @param {React.ReactNode} props.children The content to display inside the card
* @param {string} [props.title] Optional card title
* @param {string} [props.className=''] Additional CSS classes
*/
export default function Card({ children, title, className = "" }) {
return (
<div className={`card ${className}`}>
{title && <h2 className="card-title">{title}</h2>}
<div className="card-body">{children}</div>
</div>
);
}

VS Code Tips for JSDocs

Quick Generation Shortcut

Type /** directly above a function and press Enter. VS Code will automatically generate a JSDoc template with @param and @returns based on your function signature.

[Video/GIF: Demonstrating the /** + Enter shortcut]

Hover to Preview

Hover over any function name to see its JSDoc documentation rendered in a tooltip. This works for your own code and imported libraries.

Go to Definition

Press Ctrl+Click (Windows/Linux) or Cmd+Click (Mac) on a function name to jump to its definition, including the JSDoc comment.

Problems Panel

VS Code will show warnings if your JSDoc types don't match how you're using the function. Check the Problems panel (Ctrl+Shift+M or Cmd+Shift+M) for these hints.

Enable Type Checking in JavaScript

Add this comment at the very top of any .js file to enable TypeScript-style type checking based on your JSDocs:

// @ts-check

Now VS Code will show errors if you pass wrong types:

// @ts-check
/**
* Adds two numbers together
* @param {number} a First number
* @param {number} b Second number
* @returns {number} The sum
*/
function add(a, b) {
return a + b;
}
add("hello", "world"); // Error: Argument of type 'string' is not assignable to parameter of type 'number'

Common Mistakes to Avoid

❌ Mistake 1: Type in the Wrong Position

// WRONG - type is after the parameter name
/**
* @param name string The user's name
*/
// CORRECT - type is in curly braces before the parameter name
/**
* @param {string} name The user's name
*/

❌ Mistake 2: Forgetting Curly Braces Around Types

// WRONG - missing curly braces
/**
* @param string name The user's name
*/
// CORRECT
/**
* @param {string} name The user's name
*/

❌ Mistake 3: Parameter Names Don't Match

// WRONG - JSDoc says "username" but function uses "name"
/**
* @param {string} username The user's name
*/
function greet(name) {
return `Hello, ${name}`;
}
// CORRECT - names match exactly
/**
* @param {string} name The user's name
*/
function greet(name) {
return `Hello, ${name}`;
}

❌ Mistake 4: Wrong Brackets for Optional Parameters

// WRONG - using parentheses
/**
* @param {string} (name) Optional name
*/
// WRONG - using angle brackets
/**
* @param {string} <name> Optional name
*/
// CORRECT - using square brackets
/**
* @param {string} [name] Optional name
*/

❌ Mistake 5: Vague Descriptions

// WRONG - unhelpful descriptions
/**
* Does stuff
* @param {string} s The string
* @returns {string} The result
*/
function formatName(s) {
return s.toUpperCase();
}
// CORRECT - clear, specific descriptions
/**
* Converts a name to uppercase for display in headers
* @param {string} name The user's full name
* @returns {string} The name in uppercase
*/
function formatName(name) {
return name.toUpperCase();
}

When Should You Add JSDocs?

Not every function needs full documentation. Here's a practical guide:

Always Document

  • Exported functions and components — Anything you export will be used elsewhere
  • Complex functions — If the function does something non-obvious
  • Functions with multiple parameters — Especially if parameter order matters
  • Utility functions — Reusable helpers used throughout your project
  • API functions — Functions that fetch data or interact with external services

Optional to Document

  • Simple one-liner functionsconst double = (n) => n * 2 is self-explanatory
  • Internal helper functions — Private functions only used in one place
  • Event handlers with obvious nameshandleSubmit, handleClick may not need docs

Practical Rule of Thumb

Ask yourself: "If I came back to this code in 3 months, would I understand it immediately?"

If the answer is no, add JSDocs.


Generating Documentation

One of the powerful benefits of JSDocs is automatic documentation generation. JSDocs can create a complete HTML documentation website for your project.

Step 1: Install JSDocs

Add the jsdoc library to your dev dependencies:

Terminal window
npm i jsdoc --save-dev

Step 2: Run JSDocs on a Single File

You can generate documentation for a single file. For example, if your file is called utils.js:

Terminal window
node_modules/jsdoc/jsdoc.js utils.js

Step 3: View the Generated Documentation

If successful, you'll see an out folder created in your project. This folder contains your complete documentation website. Open out/index.html with the Live Server extension to view it.

[Image: Screenshot of generated JSDoc HTML documentation page showing the addNumbers function with its full documentation including description, parameters table, returns information, and example code block in a clean, styled layout]

[Video: Generating JS Docs documentation]

Generating Documentation for a Whole Project

Running JSDocs on individual files isn't practical for real projects. Let's set up a configuration file to document your entire project.

Create a Configuration File

  1. Create a conf.json file in the root of your project.
  2. Add the following code:
{
"source": {
"include": ["."],
"exclude": ["node_modules/"]
}
}

This configuration:

  • Includes all files and folders from the root directory
  • Excludes the node_modules folder (you don't want to document third-party code)

Run JSDocs with the Configuration

Use the -c flag for the configuration file and -r flag for recursive scanning:

Terminal window
node_modules/jsdoc/jsdoc.js -c ./conf.json -r

Add a Script to package.json

Instead of remembering this command, add it as a script in your package.json:

{
"scripts": {
"docs": "jsdoc -c ./conf.json -r"
}
}

Now you can generate documentation with a simple command:

Terminal window
npm run docs

JSDocs Video

We take a look at the basics of JSDocs and how to add them to a function.

[Video: Video tutorial covering the basics of JSDocs and how to add them to a function]


Exercises

Practice adding JSDocs to functions. For each exercise, add the appropriate JSDoc comments above the provided function.

Exercise 1: Basic Documentation

Add a JSDoc comment with a description to the following function:

function greetUser(name) {
return `Hello, ${name}!`;
}

Exercise 2: Adding Parameters

Add JSDoc documentation to the following function, including @param tags with types and descriptions for each parameter:

function calculateArea(width, height) {
return width * height;
}

Exercise 3: Parameters and Returns

Add complete JSDoc documentation to the following function, including a description, @param tags, and a @returns tag:

function convertToUpperCase(text) {
return text.toUpperCase();
}

Exercise 4: Adding an Example

Add JSDoc documentation to the following function that includes a description, @param, @returns, and an @example with a JavaScript code block:

function getFullName(firstName, lastName) {
return `${firstName} ${lastName}`;
}

Exercise 5: Optional Parameters

Add JSDoc documentation to the following function. Note that the greeting parameter has a default value and should be documented as optional with its default:

function createGreeting(name, greeting = "Hello") {
return `${greeting}, ${name}!`;
}

Exercise 6: Custom Types with @typedef

Create a @typedef for a Product type that has name (string), price (number), and inStock (boolean) properties. Then add JSDoc documentation to the following function using your custom type:

function formatProduct(product) {
const status = product.inStock ? "In Stock" : "Out of Stock";
return `${product.name} - $${product.price} (${status})`;
}

Exercise 7: Complex Objects

Add JSDoc documentation to the following function using dot notation to document the object parameter's properties:

function createUserProfile(options) {
return {
username: options.username,
email: options.email,
age: options.age,
createdAt: new Date(),
};
}

Exercise 8: React Component

Add JSDoc documentation to the following React component, including a description, documented props, and an @example:

function ProductCard({ title, price, imageUrl, onAddToCart }) {
return (
<div className="product-card">
<img src={imageUrl} alt={title} />
<h3>{title}</h3>
<p>${price}</p>
<button onClick={onAddToCart}>Add to Cart</button>
</div>
);
}

Exercise 9: Generate Documentation

Using the functions you documented in the previous exercises:

  1. Install JSDoc as a dev dependency
  2. Create a conf.json configuration file
  3. Add a docs script to your package.json
  4. Generate the HTML documentation and view it in your browser

Exercise Solutions

Click to reveal solutions

Exercise 1 Solution

/**
* Greets a user by their name
* @param {string} name The name of the user to greet
* @returns {string} A greeting message
*/
function greetUser(name) {
return `Hello, ${name}!`;
}

Exercise 2 Solution

/**
* Calculates the area of a rectangle
* @param {number} width The width of the rectangle
* @param {number} height The height of the rectangle
* @returns {number} The area of the rectangle
*/
function calculateArea(width, height) {
return width * height;
}

Exercise 3 Solution

/**
* Converts a string to uppercase
* @param {string} text The text to convert
* @returns {string} The text in uppercase
*/
function convertToUpperCase(text) {
return text.toUpperCase();
}

Exercise 4 Solution

/**
* Combines first and last name into a full name
* @param {string} firstName The person's first name
* @param {string} lastName The person's last name
* @returns {string} The combined full name
* @example
* ```js
* const fullName = getFullName("John", "Doe");
* console.log(fullName); // "John Doe"
* ```
*/
function getFullName(firstName, lastName) {
return `${firstName} ${lastName}`;
}

Exercise 5 Solution

/**
* Creates a greeting message with a customizable greeting word
* @param {string} name The name of the person to greet
* @param {string} [greeting="Hello"] The greeting word to use
* @returns {string} The complete greeting message
*/
function createGreeting(name, greeting = "Hello") {
return `${greeting}, ${name}!`;
}

Exercise 6 Solution

/**
* Represents a product in the store
* @typedef {Object} Product
* @property {string} name The product name
* @property {number} price The product price in dollars
* @property {boolean} inStock Whether the product is currently in stock
*/
/**
* Formats a product for display
* @param {Product} product The product to format
* @returns {string} A formatted string showing product details
* @example
* ```js
* const product = { name: "Laptop", price: 999, inStock: true };
* const formatted = formatProduct(product);
* console.log(formatted); // "Laptop - $999 (In Stock)"
* ```
*/
function formatProduct(product) {
const status = product.inStock ? "In Stock" : "Out of Stock";
return `${product.name} - $${product.price} (${status})`;
}

Exercise 7 Solution

/**
* Creates a user profile object with timestamps
* @param {Object} options The user profile options
* @param {string} options.username The user's chosen username
* @param {string} options.email The user's email address
* @param {number} options.age The user's age in years
* @returns {Object} The complete user profile with creation timestamp
*/
function createUserProfile(options) {
return {
username: options.username,
email: options.email,
age: options.age,
createdAt: new Date(),
};
}

Exercise 8 Solution

/**
* Props for the ProductCard component
* @typedef {Object} ProductCardProps
* @property {string} title The product title
* @property {number} price The product price in dollars
* @property {string} imageUrl URL to the product image
* @property {Function} onAddToCart Callback function when add to cart is clicked
*/
/**
* Displays a product card with image, title, price, and add to cart button
* @param {ProductCardProps} props Component props
* @example
* ```jsx
* <ProductCard
* title="Wireless Mouse"
* price={29.99}
* imageUrl="/images/mouse.jpg"
* onAddToCart={() => handleAddToCart(productId)}
* />
* ```
*/
function ProductCard({ title, price, imageUrl, onAddToCart }) {
return (
<div className="product-card">
<img src={imageUrl} alt={title} />
<h3>{title}</h3>
<p>${price}</p>
<button onClick={onAddToCart}>Add to Cart</button>
</div>
);
}

Exercise 9 Solution

  1. Install JSDoc:
Terminal window
npm i jsdoc --save-dev
  1. Create conf.json in your project root:
{
"source": {
"include": ["."],
"exclude": ["node_modules/"]
}
}
  1. Add to package.json scripts:
{
"scripts": {
"docs": "jsdoc -c ./conf.json -r"
}
}
  1. Generate and view:
Terminal window
npm run docs

Then open out/index.html with Live Server.


Additional Resources

Lesson Complete!

Great job! You've finished this lesson. Ready to continue?