DEV Community

Jerry Satpathy
Jerry Satpathy

Posted on

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 🧑🏻‍💻

Top comments (3)

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.

Collapse
 
j3rry320 profile image
Jerry Satpathy • Edited

To write complicated types and to pick and leave some types and to write a safe type system over the dynamic js it's always a good idea to use typescript.In this article I am of the opinion that one can achieve rudimentary type safety by using jsdoc alongside tsc
Writing comments for your code (however optimal and clean you may think it is) is always a good idea. You and I have a clear difference of opinion there.
Also yes thanks for pointing it out, I will edit the article to mention adding ts to your dev dependencies
Ps I am not pretending ts is a hurdle. Setting up typescript for your existing as well as new project is pretty straight forward
I am mentioning how all this can be done using jsdoc and writing plain old js
Sorry for the late response. I was AFK

Collapse
 
brense profile image
Rense Bakker

We don't have a difference of opinion. I'm just pointing out that exactly what you are doing with jsdoc + ts can be done with just ts. You're only adding jsdoc to have a different syntax of types inside code comments, instead of inline types.