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.
Discussion