Disclaimer: This article was written in 2016, most information are outdated.
I recently 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
1- package.json
2- gulpfile.js
3- lib/myFile.ts
4- spec/myFile.spec.ts
5- index.ts
6- tsconfig.json
1. package.json
1{
2 "name": "my-package",
3 "version": "0.0.0",
4 //...
5 "main": "dist/index.js", // for import from nodejs environments
6 "typings": "definitions/index", // TypeScript definitions
7 "typescript": {
8 "definition": "definitions/index" // TypeScript definitions
9 },
10 //...
11 "devDependencies": {
12 "@types/node": "~6.0.46", // needed for Node.js targeting
13 //...
14 },
15 "scripts": {
16 "test": "gulp test",
17 "release": "standard-version" // amazing package, seriously !
18 },
19 //...
20 "dependencies": {
21 "@types/jasmine": "^2.5.38" // need for using jasmine in TS !
22 }
23}
2. tsconfig.json
1{
2 "compilerOptions": {
3 "lib": ["es6"], // we target Node.js(v6)
4 "module": "commonjs", // export compatibility
5 "target": "es5", // we target Node.js(v6)
6 "moduleResolution": "node", // we target Node.js(v6)
7 "declaration": true, // generate TypeScript definitions
8 "rootDir": ".",
9 "outDir": "dist", // transpile JS in this directory
10 "types" : ["node", "jasmine"] // only use needed types
11 },
12 "include": [
13 "index.ts",
14 "lib/**/*",
15 "spec/**/*"
16 ]
17}
3. gulpfile.js
The gulpfile is dead-simple.
It just uses:
- gulp-typescript
- gulp-jasmine
1gulp.task('build', function() {
2 const merge = require('merge2');
3 const tsProject = ts.createProject('tsconfig.json');
4
5var tsResult = tsProject.src()
6 .pipe(tsProject());
7
8return merge(\[
9 tsResult.dts.pipe(gulp.dest('./definitions')),
10 tsResult.js.pipe(
11 gulp.dest(tsProject.config.compilerOptions.outDir)
12 )
13 \]);
14});
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 :
1import * 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 :
1gulp.task('test:run', function() {
2 return gulp.src('dist/spec/\*\*').pipe(jasmine())
3});
4// ...
5gulp.task('test', \[\], function(cb) {
6 runSequence('clean', 'build', 'test:run', cb);
7});
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 !”