Charly Poly
Nov 28, 2016 · 2 min read

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


Note: This article will be soon updated in TypeScript Essentials.
Subscribe and stay tuned !
👋


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": [
"index.ts",
"lib/**/*",
"spec/**/*"
]
}

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()
.pipe(tsProject());
return merge([
tsResult.dts.pipe(gulp.dest('./definitions')),
tsResult.js.pipe(
gulp.dest(tsProject.config.compilerOptions.outDir)
)
]);
});

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 :
https://github.com/wittydeveloper/typescript-npm-module-bootstrap/

Feel free to leave a comment, and have fun !

The French House

French mates that love web.

Thanks to Victor Mours

Charly Poly

Written by

Senior Software Engineer @ Algolia | TypeScripter, JavaScripter and Ruby-ist | https://www.algolia.com/ | http://charlypoly.dev

The French House

French mates that love web.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade