DEV Community

Jerry Satpathy
Jerry Satpathy

Posted on

2

JSDoc: Your Secret Weapon for Adding Types to JavaScript (Without the Full TypeScript Overhaul)

TypeScript is a fantastic tool for adding static typing to JavaScript, catching errors early and making large codebases more manageable. But let's be honest, sometimes a full TypeScript migration can feel like climbing Mount Everest. What if you could get most of the benefits of a statically typed system without the complete overhaul? Enter JSDoc, your secret weapon for adding types (and excellent documentation!) to your JavaScript projects.

The Power of JSDoc

JSDoc, those familiar comments above your code, can do more than explain what your functions do. They can also define types! Using @typedef and @type you can create complex, reusable type definitions in your JavaScript files. This allows you to add type safety and improve code readability without the full complexity of TypeScript.

Why JSDoc Might Be Right for You

  • Smaller Projects: For smaller projects, the overhead of a full TypeScript setup might be overkill. JSDoc offers a lightweight way to add structure and documentation.
  • Gradual Adoption: JSDoc can be a fantastic stepping stone towards TypeScript. You can start with JSDoc, generate declaration files, and gradually transition to full TypeScript if needed.
  • Existing JavaScript Codebases: Migrating a massive JavaScript codebase to TypeScript can be daunting. JSDoc allows you to introduce types incrementally, without rewriting everything at once.
  • Documentation as a First-Class Citizen: JSDoc emphasizes documentation, which is crucial regardless of your typing system. A well-documented codebase is always a plus.

Defining Types with @typedef and @type

Here's where the magic happens. Let's see how you define types using JSDoc:


/**
 * @typedef {Object} Point
 * @property {number} x - The x-coordinate.
 * @property {number} y - The y-coordinate.
 */

/**
 * Calculates the distance between two points.
 * @param {Point} p1 - The first point.
 * @param {Point} p2 - The second point.
 * @returns {number} The distance between the points.
 */
function distance(p1, p2) {
  const dx = p2.x - p1.x;
  const dy = p2.y - p1.y;
  return Math.sqrt(dx ** 2 + dy ** 2);
}

/**
 * @type {Point}
 */
const originPoint = { x: 0, y: 0 };

console.log(distance(originPoint, { x: 3, y: 4 }));
Enter fullscreen mode Exit fullscreen mode

In this example:

  • @typedef {Object} Point: Defines a Point type as an object with x and y properties, both numbers.
  • @param {Point} p1: Uses the Point type to specify the type of the p1 parameter.
  • @param {Point} p2: Uses the Point type to specify the type of the p2 parameter.
  • @type {Point}: Annotates the originPoint constant with the Point type.

Generating .d.ts Files

The real power of JSDoc types comes when you generate TypeScript declaration files (.d.ts). The TypeScript compiler (tsc) can parse your JSDoc comments and create these files for you. This means you get type-checking and code completion in your IDE, even while writing plain JavaScript!

Here's the basic tsconfig.json configuration:


{
  "compilerOptions": {
    "target": "es2020",
    "module": "commonjs",
    "outDir": "./dist",
    "declaration": true,
    "allowJs": true,
    "emitDeclarationOnly": false, // Set to true to ONLY emit .d.ts files
    "esModuleInterop": true
  },
  "include": ["./src/**/*.js"],
  "exclude": ["node_modules"]
}
Enter fullscreen mode Exit fullscreen mode

Then, run npx tsc (or tsc if installed globally) in your project directory. This will generate the .d.ts files in your outDir (./dist in this example). Below you can see the declaration file tsc generates for you

The generated declaration file for our example

The Best of Both Worlds

JSDoc with type generation provides a fantastic middle ground. You can enjoy the benefits of type safety and improved documentation without the full overhead of TypeScript. It's a great option for projects where a complete TypeScript migration isn't feasible or necessary, allowing you to gradually introduce types and improve your code quality over time.

So, next time you're thinking about adding types to your JavaScript, don't immediately jump to a full TypeScript conversion. Consider JSDoc – it might be exactly what you need.

And as always
Happy Coding 🧑🏻‍💻

Postmark Image

Speedy emails, satisfied customers

Are delayed transactional emails costing you user satisfaction? Postmark delivers your emails almost instantly, keeping your customers happy and connected.

Sign up

Top comments (1)

Collapse
 
brense profile image
Rense Bakker • Edited

can do more than explain what your functions do

Clean code man... If your functions need explanation you're doing it wrong.

Also if you add a tsconfig, you might as well use typescript 🤷 it's not the big hurdle you pretend it to be. If you have strict mode off, like in your tsconfig example, you can add or not add types whenever you like. It works literally exactly like your jsdoc examples, but without the ugly comment sections that pollute your code with redundant information or worse: add explanation to something that should have been self-explanatory.

The only time I would consider jsdoc is when you're maintaining a library and you want more human readable documentation.

Also: don't use a global version of tsc. Your code is written for a specific version of typescript and that version should be in the dev dependencies of your project.

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs