5 things to know when writing a TypeScript NPM module

Cause targeting Node.js and TypeScript in one module isn’t that easy.

Recently i started a library named spotify-graphql in TypeScript.
I wanted the library to be “importable” in Node.js(v6) and TypeScript.
Here are all the things to know that will save you hours.

Proposed Package structure

- package.json
- gulpfile.js
- lib/
- myFile.ts
- spec/
- myFile.spec.ts
- index.ts
- tsconfig.json

1. package.json

"name": "my-package",
"version": "0.0.0",
"main": "dist/index.js", // for import from nodejs environments
"typings": "definitions/index", // TypeScript definitions
"typescript": {
"definition": "definitions/index" // TypeScript definitions
"devDependencies": {
"@types/node": "~6.0.46", // needed for Node.js targeting
"scripts": {
"test": "gulp test",
"release": "standard-version" // amazing package, seriously !
"dependencies": {
"@types/jasmine": "^2.5.38" // need for using jasmine in TS !

2. tsconfig.json

"compilerOptions": {
"lib": ["es6"], // we target Node.js(v6)
"module": "commonjs", // export compatibility
"target": "es5", // we target Node.js(v6)
"moduleResolution": "node", // we target Node.js(v6)
"declaration": true, // generate TypeScript definitions
"rootDir": ".",
"outDir": "dist", // transpile JS in this directory
"types" : ["node", "jasmine"] // only use needed types
"include": [

3. gulpfile.js

The gulpfile is dead-simple.

It just uses :
- gulp-typescript
- gulp-jasmine

gulp.task('build', function() {
const merge = require('merge2');
const tsProject = ts.createProject('tsconfig.json');
var tsResult = tsProject.src()
return merge([

the build task fetches the tsconfig.json compilerOptions and generate 2 things :

  • transpiled JS in outDir
  • - TypeScript definitions in ./definitions dir (only needed if tsconfig.json specify definitions: true)

4. the “index.ts story”

When doing the following :

import * from 'my-package'

tsc will start to search for a index.ts in node_modules and all possible directories.
I found that by running tsc with — traceResolution option.

This option print all the path looked by tsc during module resolution, this is very helpful when a NPM module is “missing”.

So, when creating a TypeScript NPM module, remember to place a index.ts file a the root of your structure

5. Testing in TypeScript

In order to use Jasmine with TypeScript, you’ll need 2 things :

  • import Jasmine typings
  • transpile code to JS before running your specs

For the typing, see the “package.json” section.

Transpiling code before running the specs is done in the gulpfile, let’s take a glance :

gulp.task('test:run', function() {
return gulp.src('dist/spec/**').pipe(jasmine())
// ...
gulp.task('test', [], function(cb) {
runSequence('clean', 'build', 'test:run', cb);

As seen in “gulpfile.js” section, the build task transpile all JS (as specified in tsconfig.json) and store it in dist/ folder.

All we have to do is to send file located in dist/spec/ to jasmine, and “tada !”

I’ve made a public repo for bootstraping a TypeScript package :

Feel free to leave a comment, and have fun !