Brian Love
Angular + TypeScript Developer in Denver, CO

TypeScript 2 + Angular 1

Reading time ~11 minutes

If you want to use TypeScript in your Angular v1 application today but you are not yet ready to move to Angular v2 or v4 (yeah, it’s coming) then keep reading.


Good question.

TypeScript (TS) is the primary language for Angular going forward (2.x and 4.x). Even if you are not using Angular version 2 or greater you can still start learning and using TypeScript in your Angular apps today.

Getting Started

The first order of business is to initialize our new project, which will create a new package.json file:

$ npm init

After you have answered all of the prompts you should see a new file named package.json in your project root.

Next, install the TypeScript compiler (tsc):

$ npm install typescript --save-dev

We use the --save-dev flag so that this dev dependency is saved into the package.json file.

TypeScript Definitions

Before we can start using TypeScript we need to install the definition files. Definition files (sometimes referred to as header files in other languages) do not contain any code, rather, they describe the API for a third-party library; whether that is jQuery, React or Angular.

Let’s install the TypeScript definitions for Angular. We are going to be using the latest 1.x version of Angular, which as of the time of this writing is 1.6.1.

$ npm install @types/angular --save

Note this time I have used the --save flag so that the production dependency is saved in the package.json file.

Config tsc

In an effort to keep the setup to a minimum I am not going to be using a task runner (like Grunt) to compile the TypeScript code into ES5 JavaScript. Instead, we’ll just use the tsc command directly.

So, let’s create a tsconfig.json file to configure the TypeScript compiler:

  "compilerOptions": {
    "module": "none",
    "target": "es5"
  "files": [

We will have a single script.ts file that will be compiled to script.js, which will be included in our HTML template.

To compile our TypeScript from the root of our application execute the following command:

$ node_modules/.bin/tsc


With the pesky setup out of the way our first task is to bootstrap our app. While you can certainly use the ngApp directive to bootstrap your app, and there is nothing wrong with that approach, let’s look at bootrapping our app using the imperitive/manual way.

First, here is what our basic index.html template looks like:

<!DOCTYPE html>

    <script data-require="angularjs@1.5.8" data-semver="1.5.8" src=""></script>
    <link rel="stylesheet" href="style.css" />
    <script src="script.js"></script>



There is not much here. We include Angular and our script.js file. In the body of our html document we have a single <heros></heros> component.

Before we write the TypeScript version let’s look at traditional JavaScript for bootstrapping our app:

var module = angular.module("mySuperAwesomeApp", []);

module.component("heros", {
  template: "My heros:",
  controller: function herosController() {},
  controllerAs: "$ctrl"

angular.element(document).ready(function() {
  angular.bootstrap(document, ["mySuperAwesomeApp"]);

In our script.js file we first create a new module named mySuperAwesomeApp. Then, we create a new heros component. Finally, we wrap up our bootstrap code in a function that will be invoked when the DOM is ready.

If you rename your script.js file to scripts.ts we should start to immediately get some benefits of using TypeScript.

Though we haven’t changed any code yet our development environment should now know that our module variable is of type angular.IModule. Check out the following screen shot from VS Code showing the IntelliSense for IModule:

IntelliSense for angular.IModule


Components shipped with Angular 1.5. Components are essentially simpler and less-complex directives.

Step 1

The first step to taking advantage of TypeScript in our Angular v1 app is to use some ES2015 features, such as:

  • Template strings and
  • Arrow Functions - sometimes referred to as lambda or fat arrow functions.

Template strings use the backtick, can be multiline and include string interpolation. Arrow Functions use a short function expression syntax, and they lexically capture the this and arguments scope.

Here is a first step for our simple Angular application that uses TypeScript:

module.component("heros", {
  template: `
      <li ng-repeat="hero in $ctrl.heros"></li>
  controller: () => {
    this.heros = [
      { id: 11, name: 'Mr. Nice' },
      { id: 12, name: 'Narco' },
      { id: 13, name: 'Bombasto' },
      { id: 14, name: 'Celeritas' },
      { id: 15, name: 'Magneta' },
      { id: 16, name: 'RubberMan' },
      { id: 17, name: 'Dynama' },
      { id: 18, name: 'Dr IQ' },
      { id: 19, name: 'Magma' },
      { id: 20, name: 'Tornado' }
  controllerAs: "$ctrl"

A couple of things to note:

  • First, I am defining my template inline using the template property. The template is an unordered list of heros.
  • Second, I am defining the controller using the controller property. The controller defines the array of heros.
  • Finally, I am using the controllerAs property. My controller will be available using the name $ctrl in my template. This is the default behavior with components but I am showing this here in case you want to use a different value.

While this is a good first step there is more to TypeScript that we can take advantage of in our Angular v1 applications.

Step 2

Here are some further improvements we can make:

  1. Create a new IHero interface.
  2. Store our array of heros in a constant named HEROS that is an array of IHero objects.
  3. Update our controller to use the new HEROS constant.

Let’s take a look at these updates:

interface IHero {
  id: number;
  name: string;

const HEROS: IHero[] = [
  { id: 11, name: "Mr. Nice" },
  { id: 12, name: "Narco" },
  { id: 13, name: "Bombasto" },
  { id: 14, name: "Celeritas" },
  { id: 15, name: "Magneta" },
  { id: 16, name: "RubberMan" },
  { id: 17, name: "Dynama" },
  { id: 18, name: "Dr IQ" },
  { id: 19, name: "Magma" },
  { id: 20, name: "Tornado" }

module.component("heros", {
  template: `
      <li ng-repeat="hero in $ctrl.heros"></li>
  controller: () => {
    this.heros = HEROS;
  controllerAs: "$ctrl"

Let’s review the changes we made:

  • First, we declared a new interface named IHero that has two properties: id and name. The id will always be a number, and the name will always be a string. Both are required.
  • Next, we moved our array of heros into a constant variable named HEROS. Note the const keyword will make the array read-only. Our HEROS will be an array of IHero objects.
  • Finally, I updated the controller function expression to set the value of this.heros to the constant value of HEROS.

Ok. This is good. But there is more.

Step 3

While our app is starting to look more “TypeScript-y” there are still some more possible improvements:

  1. Create a new class that wraps up our component definition.
  2. Create a new class for our controller.

Let’s take a look:

class HerosComponentController implements ng.IComponentController {

  public heros: IHero[];

  constructor() {}

  public $onInit () {
    this.heros = HEROS;

class HerosComponent implements ng.IComponentOptions {

  public controller: ng.Injectable<ng.IControllerConstructor>;
  public controllerAs: string;
  public template: string;

  constructor() {
    this.controller = HerosComponentController;
    this.controllerAs = "$ctrl";
    this.template = `
        <li ng-repeat="hero in $ctrl.heros"></li>

  .module("mySuperAwesomeApp", [])
  .component("heros", new HerosComponent());

angular.element(document).ready(function() {
  angular.bootstrap(document, ["mySuperAwesomeApp"]);

This is a bit long, so let’s break it down:

  • First, we define a new class named HerosComponentController that implements the ng.IComponentController interface. This class replaces the arrow function expression.
  • We declare the publicly available property heros that is an array of IHero objects.
  • Within the HerosComponentController we have implemented the $onInit() method that will be invoked by Angular when all of the controllers in our component have been constructed and their bindings initialized. In $onInit() we set the value of the heros property to the value of the constant HEROS.
  • Next, we define a new class named HerosComponent that implements the ng.IComponentOptions interface. This class replaces our inline object that defined the template, controller and controllerAs properties. These are now public properties in the class. The value of each of these properties is set in the constructor function. You can also set the value immediately when defining them.
  • Note that the controller is of type: ng.Injectable<ng.IControllerConstructor>. The value of this is the HerosComponentController class.
  • Finally, note that our call to angular.component() is much shorter. We simply provide the name of the component and then a new instance of the HerosComponent class.

While our app is small now, as we continue to build out our super-awesome app we will continue to benefit from the advantages of using classes in TypeScript.


Directives are similar to components but they have more power and can be more complex. In most instances components will satisfy your requirements. However, let’s look at defining a directive using TypeScript.

In this example I have created a new file named loading-indicator-bar.ts:

export class LoadingIndicatorBarDirective implements ng.IDirective {

  public controller: any = "LoadingIndicatorBarController";
  public controllerAs: string = "loadingIndicatorBarController";
  public restrict: string = "E";

   * The link function is responsible for registering DOM listeners as well as updating the DOM.
   * @class LoadingIndicatorBarDirective
   * @method link
   * @param $scope {ng.IScope} The scope for this directive
   * @param $element {ng.IAugmentedJQuery} The JQuery instance members object.
   * @param $attributes {ng.IAttributes} An object containing normalized DOM element attributes.
   * @param loadingIndicatorBarController {LoadingIndicatorBarController} A new instance of the controller.
  public link: ng.IDirectiveLinkFn = (
    scope: ng.IScope,
    element: ng.IAugmentedJQuery,
    attributes: ng.IAttributes,
    loadingIndicatorBarController: LoadingIndicatorBarController
  ) => {

   * Create the directive.
   * @class LoadingIndicatorBarDirective
   * @method Factory
   * @static
   * @return {ng.IDirectiveFactory} A function to create the directive.
  public static Factory(): ng.IDirectiveFactory {
    return () => new LoadingIndicatorBarDirective();

This is an example of a directive that uses a controller to display a loading indicator at the top of a webpage.

My directive is very slim. The way I think of this is that it wires up an element to a controller. Let’s quickly review:

  • I created a class named LoadingIndicatorBarDirective that implements the ng.IDirective interface.
  • I’ve set up some publicly available variables named controller, controllerAs and restrict. This should look very familiar if you are used to working with directives in vanilla-JS.
  • I’ve implemented the link() method that will be invoked by Angular.
  • My link() method receives a new copy of my controller from the DI service and I call the init() method (that we will define shortly).
  • Finally, I have defined a static Factory() method whose return type is ng.IDirectiveFactory. This method returns a new function using an arrow function expression that returns a new LoadingIndicatorBarDirective.

When we want to wire up our LoadingIndicatorBarDirective we import the class and invoke the .directive() method on our module:

import { LoadingIndicatorBarDirective } from "./loading-indicator-bar";

angular.module("mySuperAwesomeApp").directive("loadingIndicatorBar", LoadingIndicatorBarDirective.Factory());


Most of the time I find that my controller is either used by a directive or I am using the ui-router for state management in my application. In this example let’s look at creating a new LoadingIndicatorBarController that will go with our LoadingIndicatorBarDirective that we previously created.

export class LoadingIndicatorBarController {

  public static $inject: string[] = ["$timeout"];

  private $element: ng.IAugmentedJQuery;
  private $loading: ng.IAugmentedJQuery;

   * Create the loading bar controller.
   * @class LoadingIndicatorBarController
   * @param $timeout {ng.ITimeoutService} The $timeout service.
   * @constructor
    private $timeout: ng.ITimeoutService
  ) { }

   * Initialize the controller.
   * @class LoadingIndicatorBarController
   * @method init
   * @param $element {ng.IAugmentedJQuery} The JQuery instance members.
   * @return {ILoadingIndicatorController} Self for chaining.
  public init($element: ng.IAugmentedJQuery): ILoadingIndicatorController {
    //store reference the $element in this scope
    this.$element = $element;

    //create container element
    var container: ng.IAugmentedJQuery = angular.element("<div class=\"loading-container\">");

    //append loading indicator bar
    this.$loading = angular.element("<div class=\"loading\">");

    //append container

    return this;

   * Hide the loading bar.
   * @class LoadingIndicatorBarController
   * @method hide
   * @return {ILoadingIndicatorController} Self for chaining.
  public hide(): ILoadingIndicatorController {
      opacity: 0
    this.$timeout(() => {
    }, 500);
    return this;

   * Set the width of the bar.
   * @class LoadingIndicatorBarController
   * @method setWidth
   * @param width {number} The percentage width of the loading indicator bar.
   * @return {ILoadingIndicatorController} Self for chaining.
  public setWidth(width: number): ILoadingIndicatorController {
    this.$loading.css({ width: `${width}%` });
    return this;

   * Show the loading indicator.
   * @class LoadingIndicatorBarController
   * @method show
   * @return {ILoadingIndicatorController} Self for chaining.
  public show(): ILoadingIndicatorController {
    this.$loading.css({ opacity: 1 });
    return this;

There is more going on here then we need to cover in detail. You can generally ignore the hide(), setWidth() and show() methods. These methods enable a developer to toggle the visibility of the loading indicator and to set the width of the loading indicator bar.

Some things to note:

  • I am using the $inject property for annotating the dependencies for our controller. The value(s) are injected into my constructor function. In this instance I am injecting the ng.ITimeoutService singleton that serves as a wrapper for window.setTimeout.
  • I have defined a public init() method that is called from my directive. It expects a single argument that is of type ng.IAugmentedJQuery. This is an element in the DOM that has been augmented by jQuery (or jqlite). It is basically the result of angular.element().

Final Thoughts

Here are some thing that I have learned along the way:

  1. The Angular TypeScript definitions are very thorough. I find myself studying the interfaces and jumping from one to the next to understand the structure.
  2. Using TypeScript (or ES2015) classes in our components, controllers and directives has some major benefits.
  3. I’m still learning and find myself refactoring after discovering a better approach. Please let me know if you have any suggestions for improvement or if I am totally messing something up. :)


I also created a demo plunker for “mySuperAwesomeApp”. Note that the plunker does not use the TypeScript source, rather I simply pasted in the result of executing tsc.

Brian Love

Hi, I'm Brian. I am interested in TypeScript, Angular and Node.js. I'm married to my best friend Bonnie, I live in Denver and I ski (a lot).