AngularJS and TypeScript

A journey through our stack

Who we are

Santi Albo

Jamie McCrindle

Our Front End Stack


Javascript with Types
Developed by Microsoft
Apache Licensed
Works on Mac OS X and Linux using Node

Why TypeScript?

Type Safety
Type Definitions for Javascript
IDE Support
Smart Code Completion
Some of ES6 Now

Some of ES6 Now

Arrow functions
(name) => "Hello " + name;
Default Arguments
function hello(name="World") { return "Hello " + name; } 
class Greeter { constructor(name) { = name; } } 
module greeters { /* encapsulated code */ } 

Type Safety and Inference

var helloString = "Hello World"!;
var helloArray = ["Hello World!"];

function helloFunction(name) { return "Hello " + name + "!"; }

Type Safety and Inference

var helloString : string = "Hello World!";
var helloArray : string[] = ["Hello World!"];

function helloFunction(name : string) : string { return "Hello " + name + "!"; }

Compiled to Javascript

var helloString = "Hello World!";

var helloArray = ["Hello World!"];

function helloFunction(name) {
    return "Hello " + name + "!";

IDE Support

Visual Studio

Web Storm and IntelliJ
Plugins for vim, Sublime Text, emacs

Writing an AngularJS App in TypeScript


/// <reference path="types/angularjs/angular.d.ts"/>
/// <reference path="types/angularjs/angular-route.d.ts"/>
/// <reference path="types/restangular/restangular.d.ts"/>

Type definitions make Javascript type safe

interface IRouteProvider extends IServiceProvider {
    otherwise(params: any): IRouteProvider;
    when(path: string, route: IRoute): IRouteProvider;
interface IRoute {
    controller?: any;
    controllerAs?: any;
    name?: string;
    template?: string;
    templateUrl?: any;
    resolve?: any;
    redirectTo?: any;
    reloadOnSearch?: boolean;


angular.module("myApp", ["ngRoute", "restangular"])
        ($routeProvider: ng.route.IRouteProvider) => {
                .when("/", {
                    templateUrl: "views/main.html",
                    controller: "MainCtrl",
                    resolve: {
                        entries: ["Restangular", (Restangular: Restangular) => {
                            return Restangular.all("entries").getList();


class MainCtrl {

    constructor(private $scope, public entries: ArrayRest<IEntryRest>) {
        $scope.vm = this;
    // ...

    public upvote(entry: IEntryRest) {
        // POST on /entries/:entryId/upvote"upvote", {}).then((updatedEntry: IEntryRest) => {
            entry.votes = updatedEntry.votes;

angular.module("myApp") .controller('MainCtrl', ['$scope', 'entries', MainCtrl]);

Building and Deploying using Grunt 

Grunt tasks

Grunt is a Javascript 'Task' runner
Tasks are defined in the Gruntfile.js
The Gruntfile.js is just a node.js script

$ grunt test$ grunt server$ grunt build$ grunt deploy

Run the tests

Unit testing with Karma and Phantom JS

End to end tests with Selenium


Config for development, QA and production

Available as an AngularJS service called 'config'

Grunt inserts the correct environment config into the service when we build

var config: Config;
angular.module('').constant('config', config);

Building the app

  • Compile the TypeScript files and embeds the settings file
  • Compile the less files
  • Concat everything within blocks in the index.html file
<!-- build:js({.tmp,app}) scripts/scripts.js -->
<script src="scripts/app.js"></script>
<script src="scripts/controllers/controllerA.js"></script> 
<script src="scripts/services/serviceB.js"></script>
<!-- endbuild -->
  • Minify the resulting css and js files
  • Append the hash of the file to the name as a cache buster   
  • Replace libraries with a CDN version
  • Put everything in a folder ready for deployment

Deploying to S3

Deploy into S3 folder using grunt-aws-s3

 var folder=timestamp + "-" + git_commit_hash 

e.g. 201401091540-fc90307

Set expiry headers for index.html

params: { Cache-Control: max-age=300 }

Update CDN

We wrote our own grunt-netdna library

Updates the pull zone to use the new S3 URL

Calls purge on the pull zone to clear out data

A few more things

Definitely Typed

If you need to depend on the latest version append the git commit hash to the url to avoid breaking future builds

Setting up the Gruntfile

Setting up the Gruntfile can take time but it's well worth it as it can automate a lot of your workflow

NPM shrinkwrap

Use npm shrinkwrap to manage your dependencies
> npm shrinkwrap

NPM registry

Switch to the EU npmjs registry mirror

npm --registry install

npm set registry 

Thank you



By jamiemccrindle