Nonetheless, folks developing libraries and frameworks sometimes want to avoid going through the friction introduced by TypeScript, such as the need to compile the code, the extra configuration needed to make it work, and the strictness of the type system. This aversion is understandable, but in this article, we’ll cover how we can get the benefits of TypeScript without switching completely.
By adding a block comment that starts with
/**, we can create a JSDoc block,
and then we use the @param tag to type the function arguments
that tools like VSCode will use to get the types the same it would do
with TypeScript, but without it. Want to make that argument optional? Just wrap
it in square brackets:
We aren’t limited to only using primitive types such as
string, but also we
can create more complex types using the @typedef tag:
This last type declaration using
@typedef might feel like it adds a lot of
“noise” in our code, so one solution is to use
.d.ts files next to our
files to declare complex types such as
User. Let’s say then that we put this
code in a
And then, the JSDoc can import the type it needs:
You might have noticed that we are using a
// @ts-check comment in each file
to enable the “power of TypeScript” on it. This comment is only necessary
because we are avoiding configuration files, but then again, we can add a little
TypeScript without compiling our code. Therefore, we only need one extra file in
the root of our project named
tsconfig.json with the following content:
the need for the
@ts-check comment. On top of that, I recommend setting the
strict option to
true to get the most out of TypeScript and avoid the most
common pitfalls of untyped code.
Our code is almost ready to give all the benefits of type checking to our
only need to generate the type files in our
prepublishOnly script in
This script will generate a
.d.ts file for each
.js file in our project. The
last step is to add a
types field to our
package.json to point to the
And that’s it! We can now publish our code to npm, and our consumers will be able to get the benefits of TypeScript without having to switch to it.
If you want to see a real-life example, you can check out this open-source package I maintain that uses this approach to provide config files for all my other projects: configs.
I’m a big fan of TypeScript and use it in all my projects, but this is still a good compromise to provide the same benefits without switching completely.
The point of this article is that there’s no good excuse to avoid DX improvements, so if you have any projects out there that you know are being used by others, it may be time to make them more friendly to your consumers.