Angular with typescript architecture

Bear with me, this is going to be a long post.

For the past several months I’ve been working on a production single page application written with AngularJS and TypeScript, and I wanted to share how myself and my team have architected the application. In case you were wondering, the app was written using typescript 0.8.3 and not 0.9.1 (which is out now with generics).

In general, I was really unhappy with a lot of the AngularJS examples I had found on the internet when researching how to structure the application, since they all looked flimsy and poorly constructed. While the examples found online were easy to read and follow, they clearly wouldn’t work with an actual large application.

I had several goals:

  • I didn’t want to have to constantly register directives/filters/controllers/etc with Angular everytime I added something
  • I didn’t want to have to update my main index.html page with any references to new files as I worked on them
  • I wanted to avoid string typing as much as possible by centralizing all string references to angular components
  • I wanted everything testable
  • I didn’t want to inline directive html templates, I wanted them in in separate html components
  • I wanted one file for each class
  • I wanted everything strongly typed

Anything less than these requirements, I felt, would compromise maintainability and extensibility for the future, especially if the app had more than one developer working on it.

Folder structure

Starting off, my folder structure looks like this:

       ├──e2e tests       
  • components – This is where all the html templates for directives go
  • css – All scss files and the final compiled app.css which is what is linked to from index.html
  • img – All statically served image files
  • js – All typescript files broken down into individually subsections. Also the definitions folder def will be seperated out from any local custom definitions if necessary, and all vendor definitions (such as angular, rxjs, jquery, etc). Also, app.ts (which will be discussed later) is the main app bootloader. _all.d.ts is an aggregate typescript def file that has all the references to the .ts files in the application
  • locales – This is where source .properties files go that can be used to auto generate typescript locale data
  • partials – This is where main angular page entrypoints go. These are the initial partials that are loaded as part of an ng-view change
  • tests – all unit tests, and e2e tests (using angular e2e scenario testing)

Wrapping Angular in OO

There’s no reason you can’t wrap the angularJS object initializers that are used to define directives, filters, controllers, etc, into strongly typed local classes. My team and I built a bunch of templates to use with IntelliJ Idea which made creating new directives/controllers/filters/services/etc extremely easy.


Let me demonstrate an example controller:

/// <reference path="../_all.d.ts" />

module {

import sharedModel = common.model;

export interface ITest extends ng.IScope{


export class Test extends ControllerBase {

public static $inject:string[] = [

constructor(private $scope:ITest) {
super(arguments, Test.$inject);

There are a few things going on here. First, there is a single aggregate definitions file that is always included. This means we don’t need to pollute each file with definitions. The _all.d.ts is also auto generated using a dependency builder we wrote (posted on my github). It finds all .d.ts files based on a dependency configuration and auto populates the all.d.ts for you.

Second, notice that the controller scope is typed with an interface. By making sure we use an interface we can guarantee we won’t try to access a field in the UI that we didn’t explicity expose.

Third, since for controllers I’m using the $inject annotation, we’re making sure to not hardcode any angular strings. Everything is centralized in an AngularGlobal class:

export class AngularGlobal {
public static $SCOPE = "$scope";
public static $COOKIE_STORE = "$cookieStore";
public static NG_COOKIES = "ngCookies";
… etc …

Also, you’ll notice that in the constructor of the controller there is a call to the base class with the inject arguments. The base class is going to validate that the arguments passed to the controller match the items in the $inject array. This way we can get fail fast runtime errors if we ask to inject something, but didn’t wire up the constructor right:

export class ControllerBase {

definedArguments(args:any):string[] {
var functionText = args.callee.toString();
var foundArgs = /\(([^)]+)/.exec(functionText);
if (foundArgs[1]) {
return foundArgs[1].split(/\s*,\s*/);

return [];

constructor(args:any, injection:string[]){

var expectedInjections =, injection);

_.each(expectedInjections, val => {
var injectionId = val[0];
var argument:string = val[1];
if(argument == null){
throw "missing injection id. Argument for " + injectionId + " is undefined. Make sure to add the ID as part of the $inject function";


So, why does moving the constructor to its own class work? Well, look at what angular wants for a controller:

myApp.controller('GreetingCtrl', ['$scope', function($scope) {
    $scope.greeting = 'Hola!';

And look at what typescript will generate for this class:

var devshorts;
(function (devshorts) {
    (function (app) {
        (function (controllers) {
            var sharedModel = common.model;
            var Test = (function (_super) {
                __extends(Test, _super);
                function Test($scope) {
          , arguments, Test.$inject);
                    this.$scope = $scope;
                Test.$inject = [
                return Test;
            controllers.Test = Test;            
        })(app.controllers || (app.controllers = {}));
        var controllers = app.controllers;
    })( || ( = {}));
    var app =;
})(devshorts || (devshorts = {}))

Disregarding all the wrapping for namespaces, you can see that the constructor for Test is just a function that takes a $scope. So, it’s the exact same thing. Now you can wire up your routes in such a way to pair partials with controllers like this:


Auto registration of services, directives, filters, and models

For our purposes, we did something slightly different with services, models, directives and filters. The reason being that controllers are always “registered” with angular via the routing. However, services, models, directives, and filters are usually registered with separate angular modules that the main app depends on. In this scenario, since it’s common to create lots of directives, etc, we didn’t want to have to manually register anything.

Let me show the model template we have:

/// <reference path="../_all.d.ts" />

module {
‘use strict’;

export interface ITestModel {


export class TestModel implements ITestModel {

public static ID:string = "TestModel";

public static injection():any[] {
return [ AngularGlobal.HTTP,
httpService => new TestModel(httpService) ];

Here there is a static ID which is the name of the model, and a static injection function that returns the array notation for injection. In the array notation the last line is the function that gets called by angular with the relevant injectable types. We preferred array notation vs $inject notation since array notation is safe to minimize. The name httpService at this point doesn’t matter, since we asked angular for it using the static AngularGlobal class discussed above.

The ID and injection functions are important, and I’ll show why in a second.

Below is how we’ve bootstrapped angular in the index.html page

     var main = new;

     // when all is done, execute bootstrap angular application      
     angular.bootstrap(document, [NG_GLOBAL.APP_NAME]);              

But what is this main class? This is a class that handles all the registration, routing, and other AngularJS setup we need.

export class Main implements IMain {

public app:ng.IModule = angular.module(NG_GLOBAL.APP_NAME,

public directives:ng.IModule = angular.module(NG_GLOBAL.APP_DIRECTIVES, []);

public services:ng.IModule = angular.module(NG_GLOBAL.APP_SERVICES, []);

public models:ng.IModule = angular.module(NG_GLOBAL.APP_MODELS, [sharedModel.AngularGlobal.NG_COOKIES]);

public providers:ng.IModule = angular.module(NG_GLOBAL.APP_PROVIDERS,[]);

public filters:ng.IModule = angular.module(NG_GLOBAL.APP_FILTERS, []);

constructor(private isAvailable:bool) {




… other methods …

Again, the app name and other dependency names are all centralized in a static class. The interesting part here is the wireFactories method which looks like this:


Lets look at wireModels

this.wire(, this.models.factory);

And finally looking at wire

* We are simulating doing something like this:
* this.directives.directive(directives.DynamicView.ID, directives.DynamicView.injection());
* The "this.directives.directive" is the function we want to call on which is the registration function
* Since the ID and injection function are statically defined in our classes and MUST be defined for
* our angular injection to work, we can type them temporarily here in this function
* This way if we add new items to any namespace that have an injection function and an ID we will
* automatically register them to the right angular module *
* @param namespace
* @param registrator
* @param byPass
wire(namespace:any, registrator:(string, Function) => ng.IModule , byPass?:(s) => bool){
for(var key in namespace){
if(byPass != null && byPass(key)) {

var injector = <IInjectable>(namespace[key]);

if(injector.ID && injector.injection){
registrator(injector.ID, injector.injection());

Since namespaces in javascript are just objects with properties, we can make an assumption that anything under the namespace is a model if it has a static ID and a static injection function. If it does, then we can register that class with the correct angular module.

Now we never have to worry about wiring up directives, filters, models, or services since at runtime they are auto wired for us. This gives application development a more native feel, just by adding the file means it exists and is available for injection.

Merging the files

I’ve read about people promoting writing everything in javascript into one file, since they don’t want to have the overhead of loading hundreds of .js files on load. I vehemently disagree here. From a development standpoint you should have one class per file. It makes it easier to split up your code, move things around, and to properly organize your application. However, in a production environment you aboslutely should distribute a single merged file. But that’s trivial. I linked to it earlier on, but the dependency tool I had also populates index.html with the appropriate script references for all .js files it finds (that are configured for it to find). If you are interested, go check out the typescript dependency builder (which I will probably blog about again later).

Assuming that your index.html page has all the relevant js files in the head, then it’s easy to write a simple script to merge all the files into one and serve that up when the application is loaded in production. In debug mode, you can serve up all the independent files, it’s just a matter of toggling your node config or your web.config (in an application).

As an example, here is an F#/C# MSBuild task class to do that for you:

public class JsMerger : Task
    public string IndexPage { get; set; }
    public List<string> JsFiles { get; set; }
    public String OutputFile { get; set; }

    public override bool Execute()
            if (File.Exists(OutputFile))

            var filesToProcess = GetFilesToProcess()
                                    .Select(f => new JsData
                                        FileName = f,
                                        FileContents = File.ReadAllText(f)

            using (var output = new StreamWriter(OutputFile))
                foreach (var file in filesToProcess)
                    output.WriteLine("/*!" + Path.GetFileName(file.FileName) + "*/");
            return true;
        catch (Exception ex)
            return false;

    private bool NotOutputOrMinFile(string f)
        var path = f;

        var check = OutputFile.Replace(".js", "");

        return (path != check + ".js") && (path != check + ".min.js");

    private IEnumerable<string> GetFilesToProcess()
        if (!String.IsNullOrEmpty(IndexPage))
            foreach (var jsFile in JsRetriever.getJsFiles(IndexPage))
                yield return jsFile;

        if (JsFiles != null && JsFiles.Count > 0)
            foreach (var f in JsFiles)
                yield return f;

Which calls into the following F# script extractor

namespace MergeJsFiles

open HtmlAgilityPack 
open System.Text.RegularExpressions
open System.IO
open System

module JsRetriever =
    let stripHtml (text:string) = 
            let mutable target = text
            let regex = [
                "<script\s*", "";            
                "\"?\s*type\s*=\s*\"\s*text/javascript\s*\"\s*", "";                 
                "</script>", "";
                "src\s*=\s*", ""
                "\"", "";
                ">", "";

            for (pattern, replacement) in regex do
                    target <- Regex.Replace(target,pattern,replacement).Trim()

            | ex -> 
                Console.WriteLine ("Error handling " + text + ", " + ex.ToString())

    let convertToAbsolute parent path =
            Path.Combine(Path.GetDirectoryName(parent), path) |> Path.GetFullPath
            | ex -> 
                Console.WriteLine ("Error handling " + path)

    let endsOn ext file = 
        Path.GetExtension(file) = ext
    let getJsFiles (defaultAspxPath:string) = 
        let doc = new HtmlDocument()

        doc.Load defaultAspxPath

        doc.DocumentNode.SelectNodes "/html/head/script/@src" 
            |> (fun i -> i.OuterHtml) 
            |> stripHtml            
            |> (convertToAbsolute defaultAspxPath)
            |> Seq.filter (endsOn ".js")


Organizing an application is hard, and everyone has their own style, but proper application organization and architecture is critical to being able to scale your codebase. Also, sometimes to make the development experience pleasant, you need to invest the time to build tools to automate boring tasks for you. Until we spent the time to create the dependency tools, working with angular and typescript was a real headache, but now it’s an absolute joy.

There are more things I haven’t covered, such as how we dealt with filters, localization, model and service aggregation (for easy injection), and http interceptors but I’ll save those for another post.

28 thoughts on “Angular with typescript architecture

  1. Hello, Anton. I have one more question: where object “_” comes from in ControllerBase class?
    Thank You.

  2. Next I want to ask is: How can I use dependency injection for this kind of class from Your article
    export class TestModel implements ITestModel {

    public static ID:string = “TestModel”;

    public static injection():any[] {
    return [ () => new TestModel() ];

    How can i inject $http services, for an instance?

  3. I guess I get it either. I should use somethink like
    public static injection():any[] {
    return [ ($http) => new TestModel($http) ];
    Am I right?

  4. Yes and no. Doing it this way you are relying on naming, so angular knows that $http is the http service. This is a bad idea cause you can’t minimize your code. Instead do something like this (forgive any typos, I’m in tokyo right now typing this on my phone:

    h => new Test(h)]

    Where AngularGlobal could be a static class and the value HTTP maps the angular id of the http service (the actual value I think is string “$http”). The variable “h” will be given the injected http service. I intentionally named it a single letter to demonstrate that using this method the naming convention no longer matters and is now safe for minimization.

    If you have more questions let me know, I am back next week and will have time to post more detailed examples in gists or on my github.

  5. Now it may be clearer what the static “ID” value is on models/directives/services, etc that I defined. You reference the string by the static class so this way you centralize all strings into one location. each model, whatever, will define its own dependencies.

    By defining the dependencies and the final construction function in static properties you can auto wire them up with angular if you follow a specific convention (I used ID and “injection”)

  6. Hello, Anton. I have one more question, not related to this article but to some thing i’m currently working on. May be You know how to register in angular dynamically loaded(via requireJS for an instance) controllers, directives, services, etc?
    Thank You.

  7. Oleg, sorry, I have no idea there. I’ll ask one of my coworkers, he may be of some help. I’ll get back to you

  8. This is very cool, Anton.
    Coming from Actionscript3 Flash/Flex background this is exactly what i was looking.

  9. This is excellent. I agree it would be great if the source code was available – it would be even better to create template and wrap it as a Node package or for VS users Nuget.

  10. Hello, Anton. Can You, please, advise me about unit test for controllers / services etc, written using this approach.

  11. Hi Anton,

    Wonderful article, so many things to learn for the guys starting with creating new projects. Please can you share the source code for this sample. It’s going to worth a lot.

  12. Can u please share the source code for the entire application structure. Will be of great help.

  13. According to the Angular help docs (, the Protractor based end-to-end tests cannot use the angular.bootstrap(...) function (which you use in index.html to manually bootstrap the application). They must use ngApp.

    This approach could be problematic for those that also use Protractor for their e2e tests.

    Are you using Protractor and if so, did you have to use any workarounds?

  14. Richard, this may have changed since I was working with angular. In reality we probably didn’t need to be manually bootstrapping angular at all and could get away with the ngApp directive.

  15. Hi Anton,

    Wonderful post you have created here! I am currently fiddling with your bits, and I wonder what the best way would be to correctly inject the underscope dependency into ControllerBase. There is an UnderscoreStatic interface in the underscore.d.ts type declaration. So now I have my controller requesting an object with this interface so it can be passed towards the ControllerBase class. For the implementation I have found the angular-module underscore-angularized with the same bower-package name. One should really prevent polluting the global namespace 🙂

  16. Hi Anton,
    I see that others have asked about the code download, but I do not see any links for it yet. Have you been able to set an example and have it downloadable?

  17. Unfortunately I left the company I was working for that had this architecture set up and have since lost the code. Won’t be happening. Sorry everyone!

Leave a Reply

Your email address will not be published. Required fields are marked *