How to Use JSDoc for JavaScript Type Checking
JSDoc bridges the gap between pure JavaScript and static type systems by using structured comment blocks to define types, describe APIs, and validate code. By pairing standard JSDoc annotations with modern editor tooling and the TypeScript compiler, developers can achieve robust documentation, intelligent autocompletion, and compile-time type safety directly in plain JavaScript files without requiring a dedicated build step or transpilation.
Understanding JSDoc Comments
JSDoc uses block comments starting with an extra asterisk
(/** ... */) placed immediately above the code construct
they describe. Inside these blocks, specific tags starting with the
@ symbol are used to describe the intent, structure, and
constraints of functions, variables, and objects.
Common tags include: * @param {type} name - description:
Documents a function parameter and its expected type. *
@returns {type} description: Defines the return type and
behavior of a function. * @type {type}: Explicitly types a
variable or property. * @typedef: Declares custom object
shapes or union types for reuse. * @deprecated: Marks code
that should no longer be used.
/**
* Calculates the total cost including tax.
* @param {number} price - The base price of the item.
* @param {number} taxRate - The applicable tax rate (e.g., 0.08 for 8%).
* @returns {number} The total cost.
*/
function calculateTotal(price, taxRate) {
return price + (price * taxRate);
}Enabling Real-Time Type Checking
Modern editors such as Visual Studio Code natively run the TypeScript Language Server in the background. This server parses JSDoc comments to provide inline type checking, parameter hints, and code refactoring suggestions.
To activate static type checking inside plain JavaScript files, you can use two approaches:
- Per-File Activation: Add
// @ts-checkon the very first line of a JavaScript file. The editor will immediately highlight type mismatches, missing properties, or invalid function calls with red squiggles. - Project-Wide Activation: Create a
jsconfig.jsonortsconfig.jsonfile in the root of the project with"checkJs": true. This enforces type checking across all JavaScript files in the project.
{
"compilerOptions": {
"checkJs": true,
"allowJs": true,
"noEmit": true
},
"include": ["src/**/*"]
}Defining Complex Types and Interfaces
JSDoc can model complex data structures using @typedef
and @property. This allows you to create reusable models
similar to TypeScript interfaces.
/**
* @typedef {Object} User
* @property {number} id - Unique user identifier.
* @property {string} name - User's full name.
* @property {string} [email] - Optional email address.
* @property {'admin' | 'member' | 'guest'} role - Union type for user roles.
*/
/**
* Updates an existing user record.
* @param {User} user - The user object to update.
*/
function updateUser(user) {
console.log(`Updating ${user.name} with role ${user.role}`);
}You can also import types directly from TypeScript definition files
(.d.ts) or other JavaScript modules using the
import() syntax inside JSDoc tags:
/** @type {import('express').Request} */
let req;Automating Documentation and Validation
Beyond editor feedback, JSDoc enables two powerful workflow enhancements:
- Static Analysis in CI/CD: You can run
tsc --noEmitvia the command line to validate all JSDoc types across your repository during continuous integration, ensuring no type errors make it into production. - HTML Documentation Generation: Using the
jsdocCLI tool, you can automatically parse your annotated codebase to generate clean, searchable HTML documentation for your APIs without writing separate markdown or web pages.
By using JSDoc, teams get the majority of TypeScript’s type safety and IDE support while maintaining pure, uncompiled JavaScript that runs natively in any browser or Node.js environment.