Publishing packages to NPM is not a particularly difficult challenge by itself. However, configuring your TypeScript project for success might be. Will your package work on most projects? Will the users have type-hinting and autocompletion? Will it work with ES Modules (ESM) and CommonJS (CJS) style imports?
Creating a TypeScript Project
Chances are that if you are reading this, you already have a TypeScript project set up. If you do, you might want to skip to the next steps or stay around to check for discrepancies.
Let's start by creating our base Node.js project and adding TypeScript as a development dependency:
npm init -y
npm install typescript --save-dev
You likely want to structure your code inside a
src folder. So let's create your package's entry point inside of it:
Now, Node.js and browsers don't understand TypeScript, so we need to set up
tsconfig.json file to our project by running:
npx tsc --init
If we run
npx tsc now, it will scan our folder and create
.js files in the same directories as our
.ts files (which is not desirable). Let's add better configuration before we run that and make a mess.
Add the following lines to
// ... Other options
"rootDir": "./src", // Where to look for our code
Let's also add a "build" script to our
If we run
npm run build now, a new
dist folder to your
tsc for Optimal Developer Experience
We are all using TypeScript for a reason: types! But if you build and ship your package right now, no types will be shipped with it. Let's fix that by setting declaration to
true. This will generate declaration files (
.d.ts) alongside our
The declaration files already go a long way in improving support and developer experience. However, we can go further by adding declarationMap. With that, sourcemaps (
.d.ts.map) will be generated to map our declaration files (
.d.ts) to our original TypeScript source code (
While we're at it, sourceMap will add sourcemap files (
Using declarationMap and/or sourceMap means we also need to publish our source code with the package to npm.
With all that, here is our final
Things are much simpler around here. We need to specify the entry point of our package when users import it. So let's set
Other than the entry point, we also need to specify the main types declaration file. In this case, that would be
declarationMap, we also need to ship
Here's a reference
package.json with all of that:
"name": "the-greatest-sdk", // Your package name
"version": "1.0.3", // Your package version
"keywords": , // Add related keywords
"author": "liblab", // Add yourself here
Publishing to NPM
Publishing to NPM is not difficult. I strongly recommend taking a look at the official instructions, but here are the general steps:
- Make sure your
package.jsonis set up appropriately.
- Build the project (with
npm run buildif you followed the guide).
- If you haven't already, authenticate to npm with
npm login(you'll need an npm account).
Keep in mind that if you update your package, you'll need to increase the
version option in your
package.json before publishing again.
There are more sophisticated (and recommended) ways to go about publishing, like using GitHub actions and releases, especially for open-source packages, but that’s out of scope for this post.
By following the discussed approach your typescript npm packages will now provide better type-hinting, auto-completion and support ES Modules (ESM) and CommonJS (CJS) style imports, making them more accessible and usable by a wider audience.
Here at liblab, we know that preparing your project for NPM can be annoying. That's why our TypeScript SDKs come prepared with all the necessary adjustments for proper publishing to NPM. We'll even help you set up your CI/CD for seamless publishing. Contact us here to learn more about how we can help automate your API’s SDK creation.