3 min read

TypeScript vs. jsDoc

Can jsDoc provide a similar editor experience while ditching the build step?

In a recent Javascript project I was part of, the team was given a lot of freedom regarding the choice of tech stack. We knew we didn’t want Node/NPM because our app would be part of a suite of apps in a high-security environment, and there had been a recent flare-up of security incidents with NPM packages.

So we actively researched alternative JS runtimes for testing and running scripts. Bun wasn‘t ready then, so we quickly settled on Deno. Deno has a great out-of-the-box experience, being everything from a runtime, linter, formatter, all in a single binary.

One notable feature is the TypeScript support, making TypeScript a first-class option. So we took a close look at TypeScript, and I was especially delighted, as I had some experience with C# and its static typing and prefer it over dynamic typing.

Around the same time, I learned that TypeScript is actually designed by the same guy who also made C#, Anders Hejlsberg, who also happened to design Turbo Pascal, the first programming language I learned in school. It’s a bit crazy how full circle this feels.

But the team lead after a couple of weeks decided against TypeScript, much to my dismay. So we compiled everything down to Javascript, made some manual modifications and moved on. But after having had a taste of static typing in the Javascript context and witnessing the power of Intellisense in my IDE, I just couldn’t let go of it. What had originally been a tidy workspace felt like it was quickly deteriorating into spaghetti code.

So I did some more research on alternatives for static typing in Javascript and discovered jsDoc and Flow. I found jsDoc to have better tool-integration than Flow, so I went that route.

In its simplest form, decorating an ES class with TypeScript looks something like this.

/**
 * Foo class
 * @class
 * @extends Bar
 * @description Does things
 */
class Foo extends Bar {
  
  /** @type number */
  amount;

  /**
   * @constructor
   * @param {number} amount 
   */
  constructor(amount) {
    this.amount = amount;
    this.doThing(amount); // <- throws warning for type mismatch
  }

  /**
   * @method
   * @param {string} name
   * @description Does things
   */
  doThing(name) {
    console.log("Doing things " + name);
  }
  
}

As you can see in the following screenshot, in an IDE like Webstorm, this gives us some nice visual type hints and a warning regarding type mismatch.

In Visual Studio Code you have to add //@ts-check to the top of the file to enable type-checking (which uses TypeScript under the hood). It doesn’t give you the visual hints Webstorm does, but it also recognises the type mismatch and gives you some Intellisense.

I think with these simple annotations, jsDoc can give you 90% of the editor user experience that TypeScript gives you, without requiring a build step.

After dropping TypeScript in the aforementioned project, I became quite happy with this solution, as it doesn’t require a build step or any special tooling.

Subscribe to get my latest posts delivered to your inbox.

Leave a reply

To respond on your own website, enter the URL of your response which should contain a link to this post's permalink URL. Your response will then appear (possibly after moderation) on this page. Want to update or remove your response? Update or delete your post and re-enter your post's URL again. (Find out more about Webmentions.)