DEV Community

Cover image for Building and Publishing Your TypeScript Code as a NPM Package
João Textor
João Textor

Posted on

Building and Publishing Your TypeScript Code as a NPM Package

I love open-source software. The previous couple of weeks, I posted about how I created a key generator and how I tested the code using jest.

Today, time has come to publish that code as a library on, so it can be consumed by anyone.

Are you ready for this?

Table of Contents


(Scroll to Top)

This article explains how to publish a TypeScript project as an open-source library on It covers the following steps:

  1. Ensure you have an account and a suitable npm version.
  2. Install the tsup library for bundling TypeScript projects.
  3. Log in to your account using the npm CLI.
  4. Configure your tsconfig.json file with specific options.
  5. Set up your package.json file with essential package details.
  6. Use the fix-tsup-cjs library to improve CommonJS module usage.
  7. Build your project with npm run build.
  8. Test the installation with npm install . -g.
  9. Finally, publish your package to with npm publish.

First, the requirements

(Scroll to Top)

First of all, before we start the publishing process, we need to make sure:

  1. We've created and account on
  2. Our npm version is at least 9.8 (I've used 10.1, but 9.8 is fine)

Dependency installing

(Scroll to Top)

We are going to use a library called tsup to bundle our TypeScript project. So, make sure you install it by running:

npm install tsup --save

Logging in to npm

(Scroll to Top)

After you've created your account on, login to it using the npm cli. You can type it using the terminal inside VS Code if you want:

npm login

After hitting 'Enter', you'll see the following message.

Terminal message saying to hit Enter to open the browser

Just hit 'Enter' again to open the login page in your web browser. You will receive an One-time Password, so check your email and paste it in the form.

Web page asking for the One-time password

Your CLI should show a message like this: Logged in on

You are good to continue!

Configuring tsconfig.json

(Scroll to Top)

Here we are making some configuration so tsup creates the bundle correctly.

Here are the options you should enable in your tsconfig.json (some may already be enabled):

  "compilerOptions": {
    /* Language and Environment */
    "target": "ES2016" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */,
    /* Modules */
    "module": "CommonJS" /* Specify what module code is generated. */,
    "noEmit": true /* Disable emitting files from a compilation. */,
    "esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */,
    "forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */,
    /* Type Checking */
    "strict": true /* Enable all strict type-checking options. */,
    "noUncheckedIndexedAccess": true /* Add 'undefined' to a type when accessed using an index. */,
    "skipLibCheck": true /* Skip type checking all .d.ts files. */
  "include": ["./"],
  "exclude": ["node_modules"] // which files to skip
Enter fullscreen mode Exit fullscreen mode

Configure package.json

(Scroll to Top)

Configuring the package.json file correctly is a crucial part in packaging and publishing your code to, so I will briefly describe the configurations I make.

First, let's see the configuration file, and later I will explain it.

  "name": "easy-key-generator",
  "version": "1.1.9",
  "description": "Easy library for generating secret keys.
It supports various features like groups, separators,
key format, and the possibility of generating multiples
keys at once.",
  "main": "dist/index.js",
  "module": "dist/index.mjs",
  "types": "dist/index.d.ts",
  "files": [
  "scripts": {
    "dev": "tsc --watch",
    "build": "tsup index.ts --format cjs,esm --dts && npx fix-tsup-cjs",
    "lint": "tsc",
    "test": "jest"
  "author": "João Textor",
  "license": "MIT",
  "repository": {
    "type": "git",
    "url": ""
  "keywords": [
    "key generator",
    "code generator"
  "devDependencies": {
    "@types/jest": "^29.5.5",
    "@typescript-eslint/eslint-plugin": "^6.7.0",
    "@typescript-eslint/parser": "^6.7.0",
    "eslint": "^8.49.0",
    "jest": "^29.7.0",
    "prettier": "^3.0.3",
    "ts-jest": "^29.1.1",
    "tsup": "^7.2.0",
    "typescript": "^5.2.2"
Enter fullscreen mode Exit fullscreen mode
  • name is the name of your package. Try choosing an unique one. Search for existing packages in
  • version: self-explanatory. I started with 1.0.0, but you're free to choose what you want. Be aware that each time you publish to, the next time it must contain a newer version.
  • description: this is where you briefly describe what your packages does.
  • main: this is where you declare the path to your main bundled file (which not yet exists). This is the javascript file which users will import using import.
  • module: this is the bundled javascript file to be imported using require, as a commonJS module.
  • types: the path to your d.ts file, which contains your types.
  • scripts: here we created a build script that will call tsup to bundle our index.ts, which is our project's main file; we've passed the option --format with cjs,esm params, which will create the commonJS file and a ES Module file; finally, the --dts option is telling tsup to create our type file with d.ts extension. Next we will call npx fix-tsup-cjs. Why? I'll explain later on.
  • author: This is where you put your name, so everyone can blame you publicly if your library introduce bugs into their projects (just kidding...or not!)
  • license: You can inform an open-source license here if you want.
  • repository: want to make easier for people to yell at you online? Place the repository to your library here 😅. They might also submit a PR to fix your undesired bugs 😄.

Explaining the npx fix-tsup-cjs

(Scroll to Top)

When bundling your project using tsup, you might notice that when importing the CommonJs module using something like const KeyGenerator = require("easy-key-generator"); when calling your class' constructor you must type this: new KeyGenerator.default(). Also, when calling a method, let's say generate(), you need to call it by using KeyGenerator.default().generate.

This sucks, right? Why can't you instantiate your class by using only KeyGenerator()?

Well, the library fix-tsup-cjs enables you to do exactly that, that's why we executed it after bundling our project using tsup.

Building our project

(Scroll to Top)

Well, now that everything is setup correctly, is time for us to build our project.

Just type npm run build in your terminal in the root of your project and hit 'Enter'.


(Scroll to Top)

Before publishing the package, your should test installing it.

To test the install, type npm install . -g in the root of your project. NPM should be able to install it globally as any other package.

If anything goes wrong in this step, it means something is wrong with your configuration.


(Scroll to Top)

Finally, it's time to publish your package to Type npm publish, get your fingers crossed and TA-DA!

Congratulations, you've successfully published your TypeScript code to! It is now available to the npm community.

In this guide, we've covered the essential steps to publish your TypeScript project on By following these steps and maintaining your package, you can share your code with the world and contribute to the open-source community. Happy coding!

If you did read through the entire post until here, please leave a reaction and a comment, and hit the follow button because next week we will be learning how to automatize the work of publishing a node package by using GitHub Actions!

Until next week!

Top comments (0)