Light Type Checking With JSDoc

February 10, 2019

/**
 * JSDoc is perfect for light static type checking! 
 */

Static type checking is good. It allows our IDE to understand our code better, provides a better debugging experience, and makes the logic easier to reason with.

But you might not need to set up TypeScript or Flow yet just for some light type checking. JSDoc, similar to JavaDoc if you know Java, is a perfect lightweight solution for this purpose.

Since they are really just comments, we don’t need a transpile process in order to benefit from JSDoc. Although the V8 engine doesn’t care about JSDoc type definitions, any modern IDE will pick them up and use the definitions to better assist us continue with our work. Drop in some JSDocs now and you can instantly see some results!

Defining Type With Native JS Types

As we all know, JavaScript has several native types: string, number, boolean, Object and of course undefined and null. Instead of directly defining the type of a variable when we declare it - like with Java, TypeScript or anybody else - we pop up a comment block right above our declaration with a @type line.

/**
 * I am a happy foo.
 * 
 * @type {string}
 */
const foo = 'bar';

Of course, if we want something concise:

/**
 * @type {string}
 */
const foo = 'bar';

Other than the basic types we mentioned above, we can also have arrays of things.

/**
 * @type {string[]}
 */
const foos = ['bar', 'bar', 'bar'];

If we want to allow the type of foo be either string or number, we can also use {string | number} for annotation.

/**
 * @type {string | number}
 */
const foo = 42;

Defining Object Shapes

While using built-in types is handy, it would be quite useless if we can’t create our own compound types for an object in a certain shape!

For this purpose, we create an additional JSDoc comment as a @typedef for the shape itself.

// define first
/**
 * @typedef {Object} Galaxy
 * @property {number} id
 * @property {string} name
 * @property {boolean} isBig
 */

// use later
/**
 * @type {Galaxy}
 */
const milkyWay = {
  id: 1,
  name: 'Milky_Way',
  isBig: false,
};

Of course, we also can nest objects like we obviously can in JavaScript.

/**
 * @typedef {Object} Galaxy
 * @property {number} id
 * @property {string} name
 * @property {boolean} isBig
 */

/**
 * @typedef {Object} Universe
 * @property {number} id
 * @property {string} name
 * @property {boolean} isReality
 * @property {Galaxy[]} galaxies
 */

Function Signature

We can also easily define function signatures with JSDoc.

/**
 * Takes a universe, makes a reality out of it.
 * 
 * @param {Universe} universe
 * @returns {Universe}
 */
const realityUniverseFrom = x => ({ ...x, isReality: true });

Of course, we don’t need to return anything all the time. In other languages, we say the return type is void, but in JavaScript it’s undefined.

/**
 * Takes a universe, makes it a reality.
 * 
 * @param {Universe} universe
 * @returns {undefined}
 */
const realityUniverseFrom = x => {
  x.isReality = true;
};

JSDoc in React

A cool thing with JSDoc is that we can also use it inside React with ease.

To define the shape of the “props” a React component can take, we can make a temporary @typedef for the props itself. Use this syntax below:

/**
 * @typedef {object} Props
 * @prop {string} key
 * @prop {string[]} options
 * @prop {Function} onSelect
 * @prop {(string | number)} width
 *
 * @extends {Component<Props>}
 */
class Selector extends Component {
  //...
}

Moar?

JSDoc is a rather comprehensive standard to document or make type checking your code. Although mostly I only use the JSDoc features above, the official documentation can give you a much more thorough look into the more advanced stuff available in JSDoc.

The truth though is that if I want to invest more into static typing in a project, I would choose TypeScript instead of JSDoc. As you have seen, writing @param, @typedef all the time can become somewhat tedious. Importing @typedefs from another file might unfortunately not work out of the box in most of the cases, and thus needs a bit fiddling to get it all set up.

However, if you are working on a small project, want a lightweight type checking solution, or due to restrictions it’s simply not ideal to use a compiler to strip off the type definitions, JSDoc then is the perfect tool for you!