How to create NPM packages with TypeScript
Tags: webdev, javascript, typescript, tutorial
Published: 2023-03-18 20:54:19

NPM (Node Package Manager) is a package manager for JavaScript. It is used to install, share, and manage packages or modules that can be used in Node.js applications or in web browsers. NPM allows developers to easily manage their dependencies and keep track of the packages they are using in their projects.

NPM has a command-line interface that developers use to install packages, update packages, and manage dependencies. NPM also provides a registry where developers can publish their own packages and make them available to others. We will be investigating how we can publish our own package so that we (or anyone else) can use it in their projects. We are also going to be incorporating TypeScript for better compatibility.


## Create an NPM account

First, we will need to create an NPM account. Lucky for us, this is free. There are paid plans if you wish to publish packages privately or as a team.

Navigate over to [https://www.npmjs.com/signup](https://www.npmjs.com/signup)

![NPM signup form](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/reqav76ueyuasv71mob0.png)


## Create a package

To create the package itself, we will be creating a very light-weight Node.js project. We'll start by creating a folder where this package will live and navigate to it in the terminal.


Initialize the project:
`npm init`


_We just added a **package.json** file to our project. The first property in this file is called **name** and this is very important. The name must be unique from all other npm packages in order to be published._


Install dev dependencies:
`npm install typescript tsup --save-dev`


Add scripts to **package.json**:
```
"scripts": {
  "build": "tsup index.ts --format cjs,esm --dts",
  "lint": "tsc"
},
```


Adjust main and add types and modules to **package.json**:
```
"main": "dist/index.js",
"module": "dist/index.mjs",
"types": "dist/index.d.ts",
```


Initialize **tsconfig.json**:
`npx tsc --init`


The configuration should be setup now. We can run `npm i` one more time for good measure, but now it is time to start building the package logic.

In the root directory, add an **index.ts** file. This is where our code will be exported out of. Let's also add a **src** folder with a couple of files in it called **ArrayFunctions.ts** and **StringFunctions.ts** (bonus points if you can guess what these files are going to contain).

We should have a file structure that looks something similar to this:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zl2ck30p2kr6biy8nf0f.png)


In **ArrayFunctions.ts**, let's add the following code:
```
export function shuffle(array: any[]): any[] {
  let currentIndex: number = array.length;
  let temporaryValue: any, randomIndex: number;

  while (currentIndex) {
    randomIndex = Math.floor(Math.random() * currentIndex);
    currentIndex--;

    temporaryValue = array[currentIndex];
    array[currentIndex] = array[randomIndex];
    array[randomIndex] = temporaryValue;
  }

  return array;
};

export function unique(array: any[]): any[] {
  return array.filter((v, i, a) => a.indexOf(v) === i);
};
```


In **StringFunctions.ts**, let's add the following code:
```
export function capitalize(string: string): string {
  return string.charAt(0).toUpperCase() + string.slice(1).toLowerCase();
};

export function capitalizeEachWord(string: string): string {
  const eachWord = string.split(' ').map((word) => (
    word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()
  ));

  return eachWord.join(' ');
};
```


Now we need to make sure the code is exported from our **index.ts** so that when someone installs our package, they will be able to retrieve the code.


In **index.ts**, let's add the following code:
```
export * from './src/ArrayFunctions';
export * from './src/StringFunctions';
```


Last thing to do with our package's code is to run build, which we previously added script for earlier.


Build the package:
`npm run build`


## Publish the package

Our final step is to make sure the package is made available to download through NPM. We will need to log into our NPM account through our terminal and then publish.


Log into NPM:
`npm login`

_Enter your username and password, plus 2FA if you enabled it._


Publish package:
`npm publish`

_Enter your OTP is you enabled it._


_**Voilà**_! We now have a published NPM package.


## How to use

If you navigate to any other JavaScript / TypeScript project you have, you will be able to run `npm i <PACKAGE_NAME>` and download the latest version you created. Importing will look something like this:
```
import { capitalize } from '<PACKAGE_NAME>';
```


To maintain your package, you will need to take the following steps:
1. update version
2. run `npm run build`
3. run `npm publish`


Maintaining a package can take a lot of work, but for personal / smaller projects, it is pretty straight forward.


## Conclusion

We are able to get an NPM package with TypeScript up and running fairly quickly. We may not have gone over documentation and there are probably better practices to handle NPM packages, but we are now pointed in the right direction to be effective.

Check out the source code for my NPM package, [**distilled-js**](https://github.com/p14/distilled-js).