Publishing a typescript package to NPM

Publishing a javascript module to NPM is fairly straightforward. There are a couple of extra steps though when you’re writing in TypeScript.

0. Output directory and entry point assumptions

Yep, it’s step 0. We need to do this with any js package anyway. Check your package.json and make sure the main key has the correct path to the entry point of your package.

"main": "dist/index.js",

Keep in mind that we’re gonna submit compiled JavaScript files to NPM, so "main" should point to the .js file.

It’s common for TypeScript projects to store compiled js files in a separate directory not tracked by VCS (.gitignore and such). We usually call it dist. Here and further down I’m gonna assume you have this line in your tsconfig.json.

"outDir": "./dist",

1. Enable generating type declarations in tsconfig

"declaration": true, /* this goes to your tsconfig.json */

Normally tsc simply compiles .ts files to plain js. With this option switched on the compiler will also generate *.d.ts files. They carry type declarations necessary for type checking and type hinting when someone imports your module in their TypeScript application.

You’ll find the *.d.ts files in your outDir along with compiled javascript.

2. Add type declarations to package.json

Now that you have the type declarations ready, add types key to your package.json.

"types": "dist/index.d.ts",

This will allow anyone who pulls your package to use the type declarations.

3. Specify what goes in the package

By default NPM ignores whatever you put in your .gitignore which works fairly well for javascript libraries. When writing in TypeScript, however, this works against us. Mainly we don’t want to ignore our dist dir — all the meat of our package is there! Here are two ways to do that.

3.1 .npmignore

$ touch .npmignore

.npmignore overrides .gitignore when publishing. Leave it empty, and everything will just be kept in. Well, not everything (here’s a detailed doc), but this is good enough for a proof of concept.

3.2 “files” key

I personally find whitelisting clearer. You don’t want your tests and dotfiles in the release so just specify what exactly goes in it. There’s files key in package.json for it.

"files": [
  "dist/*"
],

README, LICENCE and package.json are always included.

4. Build your package

Run your typescript compiler to make sure your generated js is up-to-date.

$ tsc

This is also a good time to verify that all is well before publishing.

5. Publish to NPM

$ yarn publish

Type in your password and the package version, and you’re done. Good job!