The best documentation automation can buy
Automatic JSDoc type checking 🎉

HEADER CAPTION: Screenshot from Wikimedia's famous Visual Editor. The typo "documenation" has a red squiggly line under it indicating the spell checker has automatically detected a spelling error by the author.

Tools for validating that JavaScript documentation is current and error-free have advanced significantly over the last several years. It is now possible to detect mismatches between a program's documentation and its source code automatically using a free and open-source, industry-standard type checker. This goes way beyond typos.

JavaScript typing is loose

JavaScript is an untyped language. Unlike a typed language, a JavaScript program is always generated regardless of whether the types in it are valid. Some consider JavaScript's fast-and-loose style a feature, not a bug. Notable proponents of that viewpoint include Douglas Crockford and Paul Graham.

There have been numerous articles written on the subject, but I suspect that most reading already understand the values of clear typing. For any nontrivial program with multiple authors and any longevity, especially those likely to be found among the sprawling wikis, strong typing is much more practical and sustainable than the alternative. With good typing, one can quickly grasp the structure of a program. That is, you can conceptualize and interface with any well-typed API whether you understand how it works internally or not. Refactors are a lot easier too and while not fearless, a typed codebase is far more malleable than an untyped one. Type checks are also a great way to verify your work, just like in grade school.

Picture of a whiteboard showing the complete mathematical steps for unit conversion from 65 miles per hour to kilometers per hour.
CAPTION: 65 miles per hour is how many kilometers per hour? So long as the fractions are correct, we can validate the conversion by checking that the units cancel each other out. In type checking, our function parameters, function return types, and object properties must align in a similar way but the process is automated.

Many bugs could be caught before arriving in production if every patch had its typing validated—but don't take my word for it. Phan, the PHP type checker, is now a required validation test for any change to MediaWiki Core as well as many extensions. It's like a bunch of built-in unit tests specifically for types. Without automation, these tests can require thousands of lines of hand written code that are tedious and time consuming to author, read, and maintain (e.g., see the otherwise excellent Popups extension). In the worst cases, no tests are written at all.

Photograph of the interior of a pocket watch showing intricate gears and fine craftsmanship.
CAPTION: Types must align like clockwork or the machine stops running. Image by ElooKoN / CC BY-SA.

Documentation should be correct

Good typing is just as important in documentation. For JavaScript, documentation is largely written in JSDoc (or its deprecated competitor, JSDuck). Wikipedians seem to agree that documentation is a very good idea. If documentation is a good idea, correct and up-to-date documentation is an even better one. There's a tool for that: it's called TypeScript.

If you haven't heard of TypeScript yet, it may be because it's not very common at Wikimedia except for the uber-amazing work by the WMDE and Wikidata communities (e.g., see wikibase-termbox which is over 80% TypeScript) as well as explorations several years back by Joaquín Oltra Hernández. However, it is now immensely popular globally and proven itself by capability to be far more than just a fashionable trend from 2012.

So what is TypeScript exactly? TypeScript is JavaScript with types. Whether you choose to use it for functional code like WMDE or not, TypeScript features the ability to lint plain JavaScript files for the type correctness of their JSDocs. You don't need Webpack and you don't need to make any functional changes to your code (unless it's incorrect and out-of-sync from the documentation—i.e., bug fixes). Your JavaScript is the same as it ever was but now, if your documentation and program don't match, TypeScript will report an error.

This isn't just better documentation, it's documentation as accurate as we can write in an automated way. Who doesn't want better documentation?

What changes are needed?

Typing at the seams. In practice, this usually means documenting function inputs and outputs, and user types using JSDoc syntax. E.g.:

JSDocs
/**
 * Template properties for a portlet.
 * @typedef {Object} PortletContext
 * @prop {string} portal-id Identifier for wrapper.
 * @prop {string} html-tooltip Tooltip message.
 * @prop {string} msg-label-id Aria identifier for label text.
 * @prop {string} [html-userlangattributes] Additional Element attributes.
 * @prop {string} msg-label Aria label text.
 * @prop {string} html-portal-content
 * @prop {string} [html-after-portal] HTML to inject after the portal.
 * @prop {string} [html-hook-vector-after-toolbox] Deprecated and used by the toolbox portal.
 */

/**
 * @param {PortletContext} data The properties to render the portlet template with.
 * @return {HTMLElement} The rendered portlet.
 */
function wrapPortlet( data ) {
  const node = document.createElement( 'div' );
  node.setAttribute( 'id', 'mw-panel' );
  node.innerHTML = mustache.render( portalTemplate, data );
  return node;
}

CAPTION: If this code was undocumented or the types inaccurate, would you always get the data properties right? Maybe you would, but what about everyone else?

Most programmers are already typing their JavaScript to some extent with JSDocs, so often only refinements are needed. In other cases, TypeScript's excellent type inference abilities can be leveraged so that no changes are required.

Type definitions are a useful supplement to JSDocs. Definitions are non-functional documentation that support type annotations inline. For example, the definition of the powerful but fantastically loose jQuery API could find marvelous utility in many Wikimedia codebases for at-your-fingertips documentation needs. Another very relevant example that ships with TypeScript itself is the DOM definition, which will alert you to misalignments such as attempting to access a classList on a Node instead of an Element. Thorough type checking is similar and the perfect complement to ESLint checks for ES5-only sources or more broadly ESLint's safety checks.

Type definitions are also a convenient way to describe globals and, more generally, share types. Definitions are either shipped with the NPM package itself or DefinitelyTyped (e.g., npm i -D @types/jquery) and are now standard practice for most noteworthy JavaScript libraries. Imagine if this degree of accuracy could be achieved in some of our most well-used codebases. Integrations between skins, extensions, Core, and peripheral libraries would be validated for alignment. It would be harder to break things and a much more welcoming experience for newcomers.

npm install jsdoc typescript → tsconfig.json → tsc → Document!

The actual project setup for adding documentation checks to an existing repository is minimal and requires no functional changes:

  1. Add JSDoc and TypeScript as NPM development dependencies. Optionally: add any missing types for third-party libraries used.
  2. Add a tsconfig.json to tell TypeScript to lint JavaScript documentation you wish to validate.
  3. Add tsc to the project's NPM test script.

The real work is in fleshing out the missing documentation with JSDocs. However, TypeScript is quite flexible about how one chooses to opt in or out of documentation validation. If code isn't worth documenting, it's probably not worth keeping, but typing can be consciously deferred in a number of ways. The most straightforward is probably with a // @ts-ignore comment. Think of it as progressively enhanced code.

An example project setup for Vector is here which shows how typing and documentation can be retrofitted nicely even on codebases that predate TypeScript and make heavy use of sophisticated APIs like jQuery.

Editor support

It's unnecessary for setting up a project, but worth mentioning, that by ensuring that even a machine can model your documentation means that your code editor can understand it too. For most editors, this means you'll get accurate, split-second documentation lookup and documentation type checking. Visual Studio Code has a superb out-of-box experience for JavaScript including documentation awareness and code completion, but other editors are supported too.

Screenshot from Visual Studio Code integrated development environment showing the same red squigglies we saw before but this time its detecting a fatal error instead of a typo.
CAPTION: Errors are identified as you write. There's that typo again but this time it could be your next unbreak now or your next type checker error.

You would see similar output from a continuous integration job or the command line:

Animation of the same flawed code presenting an error on the command line when checked.
CAPTION: The command line output is just as informative.

And here are those excellent docs:

Screenshot of the same code editor presenting documentation in a highly integrated and useful manner.
CAPTION: Documentation is a mouse hover away. Coding with documentation at hand is a breeze and the expectation for many modern developers writing their first MediaWiki patches.

Conclusion

65 miles per hour is 104.60736 kilometers per hour. Language changes the way we think, and documentation is the encyclopedia of code. Tooling that improves our abilities to understand, reason, and express ourselves through language improves our ability to engineer.

In my own personal and professional development, I've found accurate documentation to be a great treasure that gives me confidence and efficiency in the code that I read and write. Maybe we should have the same hopes and expectations of our documentation that newcomers do. Maybe with better documentation—documentation that is as accurate as we can automate—some of Wikipedia's many JavaScript errors could be identified and eliminated as easily as changing units from mph to kph. Maybe with better documentation, we could write better software, faster. Software that users love using and developers enjoy writing. Let's get to work!

Photograph of a blank jigsaw puzzle where pieces differ only by shape.
CAPTION: Programs are like jigsaw puzzles where types are the shapes. Check assembly before shipping. Image by Muns and Schlurcher / CC BY-SA.

Thanks to Sam Smith, Joaquín Oltra Hernández, and Leszek Manicki for reviewing and providing feedback.

NOTE: Documentation on building better documentation is being written on wiki with the help of editors like you!
Written by Niedzielski on Mar 22 2020, 2:24 PM.
Programmer
Projects
None
Subscribers
Payang02, WMDE-leszek
Tokens
"Like" token, awarded by Kaartic."Yellow Medal" token, awarded by bearND."Yellow Medal" token, awarded by mmodell."Like" token, awarded by Tgr."100" token, awarded by kostajh."Like" token, awarded by ssastry."Yellow Medal" token, awarded by WMDE-leszek.

Event Timeline