Picture of Brian Love wearing black against a dark wall in Portland, OR.

Brian Love

TypeScript 2 + AngularJS

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

Updated Aug 14, 2017

I added a new section, as per request, on setting up a service using AngularJS and TypeScript.

Why?

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": "commonjs",
    "target": "es5"
  },
  "files": ["script.ts"]
}

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

Bootstrapping

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>
<html>
  <head>
    <script
      data-require="angularjs@1.5.8"
      data-semver="1.5.8"
      src="https://opensource.keycdn.com/angularjs/1.5.8/angular.min.js"
    ></script>
    <link rel="stylesheet" href="style.css" />
    <script src="script.js"></script>
  </head>

  <body>
    <heros></heros>
  </body>
</html>

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

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 start to use some ES2015 features, such as template strings. Template strings use the backtick, can be multiline and include string interpolation.

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

module.component('heros', {
  template: `
    <ul>
      <li ng-repeat="hero in $ctrl.heros">{{ hero.name }}</li>
    </ul>
  `,
  controller: function () {
    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:

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: `
    <ul>
      <li ng-repeat="hero in $ctrl.heros">{{ hero.name }}</li>
    </ul>
  `,
  controller: function () {
    this.heros = HEROS;
  },
  controllerAs: '$ctrl',
});

Let’s review the changes we made:

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 = `
      <ul>
        <li ng-repeat="hero in $ctrl.heros">{{ hero.name }}</li>
      </ul>
    `;
  }
}

angular
  .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:

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

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
  ) => {
    loadingIndicatorBarController.init(element);
  };

  /**
   * 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:

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());

Controllers

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
   */
  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\">");
    container.append(this.$loading);

    //append container
    this.$element.append(container);

    return this;
  }

  /**
   * Hide the loading bar.
   *
   * @class LoadingIndicatorBarController
   * @method hide
   * @return {ILoadingIndicatorController} Self for chaining.
   */
  public hide(): ILoadingIndicatorController {
    this.$loading.css({
      opacity: 0
    });
    this.$timeout(() => {
      this.$element.addClass("ng-hide");
    }, 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.$element.removeClass("ng-hide");
    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:

Services

Before we get into working with services in AngularJS, let’s look at how the application might be set up. First, we bootstrap our application:

import { Factories } from './factories';

angular.element(document).ready(function () {
  //module name
  const MODULE_NAME: string = 'com.brianflove';

  //create app module
  let app: ng.IModule = angular.module(MODULE_NAME);

  //create factories
  Factories.build(app);

  //bootstrap the application
  angular.bootstrap(document, [MODULE_NAME], {
    strictDi: true,
  });
});

In the code above I bootstrap a new app. Notice that I am invoking a static build() method in the Factories class. Let’s look at the Factories class:

export class Factories {

  private static COMPANIES: string = "/rest/api/companies/:id.json";

  public static build(app: ng.IModule) {

    app.factory("companiesResource", ["$resource", function($resource: ng.resource.IResourceService) {
      return $resource(Factories.COMPANIES, {
        "id": "@id"
      });
    }]);
  }
}

Let’s review the code above:

You might be asking why there is an at-symbol ( @ ) for the parameter default value. This indicates that the value will be provided via the data object when using the resource.

Now, let’s see this in action in a controller:

import { ICompany } from "../models/company";

export class CompaniesController {

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

  public company: ICompany;

  constructor(
    private companiesResource: ng.resource.IResourceClass<ICompany>
  ) {}

  getCompany(id: string) {
    this.companiesResource.get({ id: id }).$promise.then((company: ICompany) => {
      this.company = company;
    });
  }
}

I have not included all of the necessary code for this example, such as the model definition, but I think this is a good example of using our companiesResource service.

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. :)

Plunker

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.

\n \n \n \n\n \n \n \n\n```\n\nThere is not much here.\nWe include Angular and our **script.js** file.\nIn the body of our html document we have a single `` component.\n\nBefore we write the TypeScript version let's look at traditional JavaScript for bootstrapping our app:\n\n```javascript\nvar module = angular.module('mySuperAwesomeApp', []);\n\nmodule.component('heros', {\n template: 'My heros:',\n controller: function herosController() {},\n controllerAs: '$ctrl',\n});\n\nangular.element(document).ready(function () {\n angular.bootstrap(document, ['mySuperAwesomeApp']);\n});\n```\n\nIn our **script.js** file we first create a new module named _mySuperAwesomeApp_.\nThen, we create a new _heros_ component.\nFinally, we wrap up our bootstrap code in a function that will be invoked when the DOM is ready.\n\nIf you rename your **script.js** file to **scripts.ts** we should start to immediately get some benefits of using TypeScript.\n\nThough we haven't changed any code yet our development environment should now know that our `module` variable is of type `angular.IModule`.\nCheck out the following screen shot from VS Code showing the IntelliSense for IModule:\n\n![IntelliSense for angular.IModule](/posts/2016/typescript-2-plus-angular-1-typescript-intellisense.png)\n\n## Components\n\nComponents shipped with Angular 1.5.\nComponents are essentially _simpler_ and _less-complex_ directives.\n\n### Step 1\n\nThe first step to taking advantage of TypeScript in our Angular v1 app is to start to use some ES2015 features, such as template strings.\nTemplate strings use the backtick, can be multiline and include string interpolation.\n\nHere is a first step for our simple Angular application that uses TypeScript:\n\n```javascript\nmodule.component('heros', {\n template: `\n \n `,\n controller: function () {\n this.heros = [\n { id: 11, name: 'Mr. Nice' },\n { id: 12, name: 'Narco' },\n { id: 13, name: 'Bombasto' },\n { id: 14, name: 'Celeritas' },\n { id: 15, name: 'Magneta' },\n { id: 16, name: 'RubberMan' },\n { id: 17, name: 'Dynama' },\n { id: 18, name: 'Dr IQ' },\n { id: 19, name: 'Magma' },\n { id: 20, name: 'Tornado' },\n ];\n },\n controllerAs: '$ctrl',\n});\n```\n\nA couple of things to note:\n\n- First, I am defining my template inline using the `template` property. The template is an unordered list of heros.\n- Second, I am defining the controller using the `controller` property. The controller defines the array of heros.\n- 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.\n\nWhile this is a good first step there is more to TypeScript that we can take advantage of in our Angular v1 applications.\n\n### Step 2\n\nHere are some further improvements we can make:\n\n1. Create a new `IHero` interface.\n2. Store our array of heros in a constant named `HEROS` that is an array of `IHero` objects.\n3. Update our controller to use the new `HEROS` constant.\n\nLet's take a look at these updates:\n\n```javascript\ninterface IHero {\n id: number;\n name: string;\n}\n\nconst HEROS: IHero[] = [\n { id: 11, name: 'Mr. Nice' },\n { id: 12, name: 'Narco' },\n { id: 13, name: 'Bombasto' },\n { id: 14, name: 'Celeritas' },\n { id: 15, name: 'Magneta' },\n { id: 16, name: 'RubberMan' },\n { id: 17, name: 'Dynama' },\n { id: 18, name: 'Dr IQ' },\n { id: 19, name: 'Magma' },\n { id: 20, name: 'Tornado' },\n];\n\nmodule.component('heros', {\n template: `\n \n `,\n controller: function () {\n this.heros = HEROS;\n },\n controllerAs: '$ctrl',\n});\n```\n\nLet's review the changes we made:\n\n- 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.\n- 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.\n- Finally, I updated the controller function expression to set the value of `this.heros` to the constant value of `HEROS`.\n\nOk. This is good.\nBut there is more.\n\n### Step 3\n\nWhile our app is starting to look more \"TypeScript-y\" there are still some more possible improvements:\n\n1. Create a new class that wraps up our component definition.\n2. Create a new class for our controller.\n\nLet's take a look:\n\n```javascript\nclass HerosComponentController implements ng.IComponentController {\n\n public heros: IHero[];\n\n constructor() {}\n\n public $onInit () {\n this.heros = HEROS;\n }\n}\n\nclass HerosComponent implements ng.IComponentOptions {\n\n public controller: ng.Injectable;\n public controllerAs: string;\n public template: string;\n\n constructor() {\n this.controller = HerosComponentController;\n this.controllerAs = \"$ctrl\";\n this.template = `\n \n `;\n }\n}\n\nangular\n .module(\"mySuperAwesomeApp\", [])\n .component(\"heros\", new HerosComponent());\n\nangular.element(document).ready(function() {\n angular.bootstrap(document, [\"mySuperAwesomeApp\"]);\n});\n```\n\nThis is a bit long, so let's break it down:\n\n- First, we define a new class named `HerosComponentController` that implements the `ng.IComponentController` interface. This class replaces the arrow function expression.\n- We declare the publicly available property `heros` that is an array of `IHero` objects.\n- 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`.\n- 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.\n- Note that the controller is of type: `ng.Injectable`. The value of this is the `HerosComponentController` class.\n- 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.\n\nWhile 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.\n\n## Directives\n\nDirectives are similar to components but they have more power and can be more complex.\nIn most instances components will satisfy your requirements.\nHowever, let's look at defining a directive using TypeScript.\n\nIn this example I have created a new file named **loading-indicator-bar.ts**:\n\n```javascript\nexport class LoadingIndicatorBarDirective implements ng.IDirective {\n\n public controller: any = \"LoadingIndicatorBarController\";\n public controllerAs: string = \"loadingIndicatorBarController\";\n public restrict: string = \"E\";\n\n /**\n * The link function is responsible for registering DOM listeners as well as updating the DOM.\n *\n * @class LoadingIndicatorBarDirective\n * @method link\n * @param $scope {ng.IScope} The scope for this directive\n * @param $element {ng.IAugmentedJQuery} The JQuery instance members object.\n * @param $attributes {ng.IAttributes} An object containing normalized DOM element attributes.\n * @param loadingIndicatorBarController {LoadingIndicatorBarController} A new instance of the controller.\n */\n public link: ng.IDirectiveLinkFn = (\n scope: ng.IScope,\n element: ng.IAugmentedJQuery,\n attributes: ng.IAttributes,\n loadingIndicatorBarController: LoadingIndicatorBarController\n ) => {\n loadingIndicatorBarController.init(element);\n };\n\n /**\n * Create the directive.\n *\n * @class LoadingIndicatorBarDirective\n * @method Factory\n * @static\n * @return {ng.IDirectiveFactory} A function to create the directive.\n */\n public static Factory(): ng.IDirectiveFactory {\n return () => new LoadingIndicatorBarDirective();\n }\n}\n```\n\nThis is an example of a directive that uses a controller to display a loading indicator at the top of a webpage.\n\nMy directive is very slim.\nThe way I think of this is that it wires up an element to a controller.\nLet's quickly review:\n\n- I created a class named `LoadingIndicatorBarDirective` that implements the `ng.IDirective` interface.\n- 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.\n- I've implemented the `link()` method that will be invoked by Angular.\n- 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).\n- 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`.\n\nWhen we want to wire up our `LoadingIndicatorBarDirective` we import the class and invoke the `.directive()` method on our module:\n\n```javascript\nimport { LoadingIndicatorBarDirective } from './loading-indicator-bar';\n\nangular\n .module('mySuperAwesomeApp')\n .directive('loadingIndicatorBar', LoadingIndicatorBarDirective.Factory());\n```\n\n## Controllers\n\nMost 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.\nIn this example let's look at creating a new `LoadingIndicatorBarController` that will go with our `LoadingIndicatorBarDirective` that we previously created.\n\n```javascript\nexport class LoadingIndicatorBarController {\n\n public static $inject: string[] = [\"$timeout\"];\n\n private $element: ng.IAugmentedJQuery;\n private $loading: ng.IAugmentedJQuery;\n\n /**\n * Create the loading bar controller.\n *\n * @class LoadingIndicatorBarController\n * @param $timeout {ng.ITimeoutService} The $timeout service.\n * @constructor\n */\n constructor(\n private $timeout: ng.ITimeoutService\n ) { }\n\n /**\n * Initialize the controller.\n *\n * @class LoadingIndicatorBarController\n * @method init\n * @param $element {ng.IAugmentedJQuery} The JQuery instance members.\n * @return {ILoadingIndicatorController} Self for chaining.\n */\n public init($element: ng.IAugmentedJQuery): ILoadingIndicatorController {\n //store reference the $element in this scope\n this.$element = $element;\n\n //create container element\n var container: ng.IAugmentedJQuery = angular.element(\"
\");\n\n //append loading indicator bar\n this.$loading = angular.element(\"
\");\n container.append(this.$loading);\n\n //append container\n this.$element.append(container);\n\n return this;\n }\n\n /**\n * Hide the loading bar.\n *\n * @class LoadingIndicatorBarController\n * @method hide\n * @return {ILoadingIndicatorController} Self for chaining.\n */\n public hide(): ILoadingIndicatorController {\n this.$loading.css({\n opacity: 0\n });\n this.$timeout(() => {\n this.$element.addClass(\"ng-hide\");\n }, 500);\n return this;\n }\n\n /**\n * Set the width of the bar.\n *\n * @class LoadingIndicatorBarController\n * @method setWidth\n * @param width {number} The percentage width of the loading indicator bar.\n * @return {ILoadingIndicatorController} Self for chaining.\n */\n public setWidth(width: number): ILoadingIndicatorController {\n this.$loading.css({ width: `${width}%` });\n return this;\n }\n\n /**\n * Show the loading indicator.\n *\n * @class LoadingIndicatorBarController\n * @method show\n * @return {ILoadingIndicatorController} Self for chaining.\n */\n public show(): ILoadingIndicatorController {\n this.$element.removeClass(\"ng-hide\");\n this.$loading.css({ opacity: 1 });\n return this;\n }\n}\n```\n\nThere is more going on here then we need to cover in detail.\nYou can generally ignore the `hide()`, `setWidth()` and `show()` methods.\nThese methods enable a developer to toggle the visibility of the loading indicator and to set the width of the loading indicator bar.\n\nSome things to note:\n\n- 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`.\n- 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()`.\n\n## Services\n\nBefore we get into working with services in AngularJS, let's look at how the application might be set up.\nFirst, we bootstrap our application:\n\n```javascript\nimport { Factories } from './factories';\n\nangular.element(document).ready(function () {\n //module name\n const MODULE_NAME: string = 'com.brianflove';\n\n //create app module\n let app: ng.IModule = angular.module(MODULE_NAME);\n\n //create factories\n Factories.build(app);\n\n //bootstrap the application\n angular.bootstrap(document, [MODULE_NAME], {\n strictDi: true,\n });\n});\n```\n\nIn the code above I bootstrap a new app.\nNotice that I am invoking a static `build()` method in the Factories class.\nLet's look at the `Factories` class:\n\n```javascript\nexport class Factories {\n\n private static COMPANIES: string = \"/rest/api/companies/:id.json\";\n\n public static build(app: ng.IModule) {\n\n app.factory(\"companiesResource\", [\"$resource\", function($resource: ng.resource.IResourceService) {\n return $resource(Factories.COMPANIES, {\n \"id\": \"@id\"\n });\n }]);\n }\n}\n```\n\nLet's review the code above:\n\n- First, we define a new class named `Factories`. This class will build all of our services.\n- Next, a static `COMPANIES` variable is set to the resource URL for a REST API endpoint. In this example this is an endpoint for companies. Note the _:id_ placeholder for the company id value. This service is using AngularJS's [\\$resource provider](https://docs.angularjs.org/api/ngResource/service/$resource) for interacting with RESTful data sources.\n- The static `build()` method is invoked when we bootstrap our app.\n- Within the build method we invoke the `factory()` method on our app, defining a new injectable service named `companiesResource`. We use the array notation to inject the `$resource` service into the factory function, which is just the anonymous function that is the last element in the array. Our factory function returns a new resource provider, specifying the endpoint URL and the `id` parameter.\n\nYou might be asking why there is an at-symbol ( @ ) for the parameter default value.\nThis indicates that the value will be provided via the `data` object when using the resource.\n\nNow, let's see this in action in a controller:\n\n```javascript\nimport { ICompany } from \"../models/company\";\n\nexport class CompaniesController {\n\n public static $inject: string[] = [\"companiesResource\"];\n\n public company: ICompany;\n\n constructor(\n private companiesResource: ng.resource.IResourceClass\n ) {}\n\n getCompany(id: string) {\n this.companiesResource.get({ id: id }).$promise.then((company: ICompany) => {\n this.company = company;\n });\n }\n}\n```\n\nI have not included all of the necessary code for this example, such as the model definition, but I think this is a good example of using our `companiesResource` service.\n\n- First, we import an interface named `ICompany`, which is an interface for the model returned from the REST API.\n- Next, we define a new controller class named `CompaniesController`. Don't worry about the name of the controller, as you'll be injecting a service into your own controllers.\n- Next, note that we have a public static `$inject` property. This property instructs the dependency injector to provide services into the class `constructor` function. The string values in the array have to match exactly to the string value specified when creating the service via the `factory` method. Also, note that the values injected into our constructor will be in the same order as specified in the array.\n- In the `constructor` function we expect to receive the `companiesResource` service that will be injected into our controller. Note that the type declaration of the service is `ng.resource.IResourceClass`. This will ensure type safety when we use the service, including the return type when we invoke verb methods.\n- Finally, in the `getCompany()` method we require the `id` string argument, and then invoke the `get()` method on the resource service that was injected. The method has a `$promise` object that we can use to invoke the `then()` method when the promise is fulfilled. Using a fat arrow function we define an anonymous function that will be invoked with the company object. We then simply store this into a public property of our class.\n\n## Final Thoughts\n\nHere are some thing that I have learned along the way:\n\n1. The Angular TypeScript definitions are very thorough. I find myself studying the interfaces and jumping from one to the next to understand the structure.\n2. Using TypeScript (or ES2015) classes in our components, controllers and directives has some major benefits.\n3. 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. :)\n\n## Plunker\n\nI also created a demo plunker for \"mySuperAwesomeApp\".\nNote that the plunker does not use the TypeScript source, rather I simply pasted in the result of executing _tsc_.\n\n\n","author":{"@type":"Person","image":"/headshots/brian-love-1.jpg","name":"Brian Love","sameAs":"https://brianflove.com/"},"datePublished":"2016-12-26T00:00:00.000Z","description":"If you want to use TypeScript in your AngularJS (Angular v1) application today but you are not yet ready to move to Angular v2 or v4 (yeah, it's coming) then keep reading.","headline":"TypeScript 2 + AngularJS","name":"TypeScript 2 + AngularJS","url":"https://brianflove.com"}