Creating an NPM module in TypeScript

I’m a great believer in type systems and we’ve recently started to use TypeScript. We want to mix TypeScript modules into our existing node.js code. However, TypeScript is a rapidly changing ecosystem, which meant I went down some blind alleys when trying to figure out how to set up an npm module. It turns out, with TypeScript 2.0, it’s really simple. Here’s one suggestion for how to get started. Begin with a directory for your project and

npm init

Set your entry point to dist/${projectName}.js. For instance, for a project called safeLeftPad, put this in package.json:

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

You’re going to need to install TypeScript if you haven’t already. Let’s install it globally, and in the project so random JavaScript hackers can still compile our module.

npm install --save-dev typescript
npm install --global typescript

Typescript uses a tsconfig.json file to configure the compiler. Let’s autogenerate one:

tsc --init

You need to edit it to output to the correct directory (dist) and set the source location. You only need to point it at the main entry point file. I also turn on noImplicitAny to keep me honest, and target es6 to get the cool stuff. My tsconfig.json now looks like this:

    "compilerOptions": {
        "module": "commonjs",
        "target": "es6",
        "noImplicitAny": true,
        "sourceMap": false,
        "outDir": "dist"
    "files": [

Add tsc as a prepublish command to package.json so the TypeScript is compiled when you package. My package.json now looks like this:

  "name": "safe-left-pad",
  "version": "0.0.1",
  "description": "",
  "main": "dist/safeLeftPad.js",
  "scripts": {
    "prepublish": "tsc",
    "test": "echo \"Error: no test specified\" && exit 1"
  "author": "Ben Blackburne",
  "license": "ISC",
  "devDependencies": {
    "typescript": "^2.0.3"

To compile your TypeScript, simply run tsc and the appropriate .js and .d.ts files are created in dist/. You don’t need autodts.

A word about typings

The first thing you are probably going to do is try and use some node modules. To do so, you need the appropriate Declaration Files for the module, which contain the type definitions. There’s a bunch of pre-existing projects for this (e.g. typings, DefinitelyTyped). However, it is now all integrated into npm and you need (in theory) do nothing more than npm install @types/${moduleName}. I’ve come across a couple of gotchas though.

Firstly, the type definitions won’t necessarily match the module version, and npm won’t care. For instance:

npm install request-promise @types/request-promise --save

At time of writing, this will happily install request-types version 4, and the definitions for version 3. In this case, I suggest you manually use the older version of request-promise:

npm install request-promise@3.0.0 @types/request-promise@3.0.0 --save

Secondly, it doesn’t seem to handle dependencies well. On compiling a project, you may find an error about missing dependencies:

node_modules/@types/request-promise/index.d.ts(10,30): error TS2307: Cannot find module 'bluebird'.

So you have to manually install the missing definitions:

npm install @types/bluebird --save