TypeScript/Grunt/Angular

April 03, 2014 | JavaScript

Since the TypeScript language is a strict superset of JavaScript, all the repetitive tasks like minification, compilation, unit testing, linting, etc, performed by Grunt can also be applied to TypeScript projects.

This post describes how to add TypeScript to an AngularJS project where task automation is performed by Grunt.

Task automation pipeline

Grunt processes a task automation pipeline defined in a Gruntfile. A sample Gruntfile is available from the Grunt website.

Yeoman as a generator for task automation pipelines

A more sophisticated Gruntfile, with reasonable defaults and best practises, is generated by Yeoman through generator-angular.

To make it easier to follow along, I will remove all globally installed npm modules on my machine:

# http://stackoverflow.com/a/9283646/467754
npm -g ls | grep -v 'npm@' | awk '/@/ {print $2}' | awk -F@ '{print $1}' | xargs npm -g rm

# There are no globally installed npm modules:
npm list -g
C:\Users\Nikos\AppData\Roaming\npm
L-- (empty)

Install generator-angular:

npm install -g generator-angular

# The following higher-level npm modules are globally installed:
npm list -g -depth=0
C:\Users\Nikos\AppData\Roaming\npm
├── bower@1.3.1
├── generator-angular@0.8.0
├── generator-karma@0.7.0
├── grunt-cli@0.1.13
└── yo@1.1.2

Gruntfile generation

Setting up a new AngularJS project through generator-angular generates all the boilerplate including the task automation pipeline (Gruntfile).

yo angular [app-name]

In case of any npm installation errors run 'npm cache clean [-g]'.

Test runner configuration

Install a karma adapter, as well as a browser launcher:

npm install karma-jasmine --save-dev
npm install karma-chrome-launcher --save-dev

Invoke Grunt via 'grunt serve' and modify a test file. Any modification in the test files invokes Karma.

TypeScript/Grunt installation

Install the command-line TypeScript compiler:

npm install -g typescript

# The following higher-level npm modules are globally installed:
npm list -g -depth=0
C:\Users\Nikos\AppData\Roaming\npm
├── bower@1.3.1
├── generator-angular@0.8.0
├── generator-karma@0.7.0
├── grunt-cli@0.1.13
├── typescript@0.9.7 <--
└── yo@1.1.2

Install grunt-typescript:

npm install grunt-typescript --save-dev

TypeScript auto-compilation

Rename all files with a .js extension to have a .ts extension and modify the Gruntfile:

typescript: {
  base: {
    src: ['<%= yeoman.app %>/scripts/{,*/}*.ts'],
    options: {
      target: 'es5',
      sourceMap: true
    }
  },
  test: {
    src: ['test/spec/{,*/}*.ts'],
    options: {
      target: 'es5',
      sourceMap: true
    }
  }
},

...

ts: {
  files: ['<%= yeoman.app %>/scripts/{,*/}*.ts'],
  tasks: ['typescript']
},
tsTest: {
  files: ['test/spec/{,*/}*.ts'],
  tasks: ['typescript:test']
},

The file comparison output should be similar with the image shown below:

Image

Linting configuration

Remove the indentation setting from JSHint since TypeScript indents code idiomatically.

Image

Declaration source files usage

Most, if not all, of the TypeScript declaration source files are available by installing DefinitelyTyped:

bower install DefinitelyTyped --save-dev

Create an _all.ts declaration source file containing each necessary declaration:

/// <reference path='../bower_components/DefinitelyTyped/angularjs/angular.d.ts' />
/// <reference path='controllers/main.ts' />
/// <reference path='app.ts' />

The '_all.ts' declaration source file is a convenient way of referencing all declaration sources in one line: /// <reference path='[relative-path-to-all.ts-file]' />

A similar pattern can be applied to the test files:

/// <reference path='../../app/bower_components/DefinitelyTyped/angularjs/angular-mocks.d.ts' />
/// <reference path='../../app/bower_components/DefinitelyTyped/jasmine/jasmine-1.3.d.ts' />
/// <reference path='../../app/scripts/controllers/main.ts' />

Coding in TypeScript

The TypeScript language services is available as an official add-in for Visual Studio as well as an unofficial, but rather excellent, add-in for Sublime Text.