Browse Category: TypeScript

A high level look at Angular 2

Developed by Google, Angular 2 is the newest version of the popular Single Page Application (SPA) framework. Angular 2 is a step in a new direction compared to previous versions, but has keep all the best characteristics and “lessons learnt” to deliver a fast, fully featured and rich ecosystem.

About Angular 2

Angular 2 impacts your whole application, or at the least, a section of it, rather than specific pages. Angular 2 is best suited to new (“greenfield”) development, as it can be relatively tricky to migrate legacy code (Angular 1.x code) to the new version. Angular 2 has new concepts, syntax, methodologies, and opinions, but is comparable to as previous versions in the way it works.

If you have been following Angular development since “the early days” of beta 1, then its been a very rocky road for you. Even now (this post was written around the release of RC5), the API is still evolving and new features are being added. Whilst this experience has been hard for early adopters, I believe the end result will be a fantastic, easy to use, and performant framework with a lower barrier to entry for all.

Overview

The purpose of this post is to discuss the core concepts of Angular 2. We’re not looking to dive into the details at this point, a follow up post on that will come later. We will discuss; pre-processors, build tools, components, dependency injection, interpolation, pipes, directives, event bindings, two way data binding, lifecycle hooks, routing, services and the HTTP client.

I have a side project on Github, named Angular2Todo, which is an Angular 2 todo application written with Angular 2, Universal Angular, and ASP .NET Core. If you’re interested in server side rendered Angular, please check that out.

This post is based on my own experience with Angular 2, and most of the knowledge has come from developing real world applications, including this one on Github.

Going forward, we will refer to Angular 2 simply as “Angular”. Old versions of Angular will be referred to by their version number explicitly.

TypeScript, Babel, ES6/ES5

It is hard to talk about Angular 2 without discussing TypeScript (See TypeScript playground for a live interactive demo). Angular was originally written using AtScript, which was an extension of TypeScript (TypeScript with additional functionality). However, after much collaboration between the Angular team and the TypeScript team, it was decided to use TypeScript exclusively instead.

Angular is written using TypeScript, however, you don’t necessarily have to write you Angular code using TypeScript, you could use; Babel, ES5 or ES6 if you prefer. If you are familiar with Google Dart, that is also supported.

I believe that Angular 2 applications are most commonly being developed using TypeScript, so I’ll use TypeScript throughout this post. If you need a summary of TypeScript, check out my TypeScript Beginners Guide on this website, DeveloperHandbook.com.

At a high level, TypeScript is JavaScript. You can convert all your existing JavaScript code to TypeScript as easily as changing the file extension from JS to TS. The most useful feature of TypeScript is its transpiler, which takes your TypeScript code (which is basically ES6), and converts it into ES5. Why would you want to do this? Most developers will want to utilise the new language features of ES6, ES7 and beyond, whilst not having to worry about cross browser compatibility. Support for ES6 is shaky at best on the desktop (Microsoft Edge, I’m looking at you), and very poor across mobile devices. TypeScript takes this pain away by converting your code to ES5, which is stable and does have excellent support.

Build tools

As we’re working with TypeScript, and potentially other tools as well, it makes sense to use build tools like Webpack or Gulp. Build tools can automate repetitive tasks, such as; transpiling the code (TypeScript to ES5), bundling (taking all your individual assets and merging them into one big file), minification (compressing that file for faster delivery to the client), and injection (referencing the new resource in the HTML).

Build tools can also watch your changes, and automatically build and refresh the browser automatically, so that you can focus on writing code and developing your application.

The Angular documentation, once you get beyond the absolute basics, encourages you to split your components (we will discuss these more next) into individual concerns. Your JavaScript, styles (CSS) and markup (HTML) are to be placed in individual files (component.js, component.css, component.html). This results in a lot of “chatter” between the client and server and can slow down the user experience (particularly on slower, mobile devices). Build tools can solve this problem by automatically injecting the markup and styles into your JavaScript files at compile time. This is certainly not a task you would want to perform manually!

Personally I have worked with both Gulp and Webpack when developing Angular applications. I prefer Webpack for how well it works, but I do not like the configuration aspect. Gulp is much easier to configure, but not as powerful (my feeling) as Webpack.

I have an example Gulp and Webpack configuration file on GitHub, that have both been used in real world applications.

Components

Components are the basic building blocks of all Angular applications. Components are small and have their own state per instance (meaning you can reuse the same component many times on a single page without it colliding with other instances). Components closely follow the open standard for Web Components, but don’t have the same pain of cross browser support (the Web Components standard has not been finalised yet). Components are a group of directly related JavaScript (logic), CSS (style) and HTML (markup), which are largely self contained.

Components in Angular are defined using the @Component class decorator, which is placed on a class, and take “metadata” which describe the component, and its dependencies.

A component might look like this;

import { Component } from '@angular/core';
import { ROUTER_DIRECTIVES } from '@angular/router';

@Component({
    selector: 'my-app',
    directives: [...ROUTER_DIRECTIVES],
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.css']
})
export class AppComponent {

}

This is ES6/TypeScript code. We create a class, called AppComponent using the class keyword. The export keyword makes the class “public”, so that it can be referenced elsewhere throughout the application.

The @Component directive takes an object that describes the component.

  • Selector: This is used in your markup. The selector is how you refer to the component in HTML. In this example, the code would be; <my-app></my-app>
  • Directives: These are other components that you want to utilise in the components markup
  • TemplateUrl: The path on the file-system to the markup
  • StyleUrls: A string array of all the CSS files used to style the component

There are many values that can be passed in here, the main values are displayed.

About styling

Why does Angular load the styles in this manner? Take the following markup (I’ve trimmed this slightly for simplicity);

<tr>
    <td>...</td>
    <td>{{asDate(calibrationDue.date) | date}}</td>
    <td>{{asDate(calibrationDue.expiration) | date}}</td>
    <td>{{calibrationDue.registration}}</td>
    <td>{{calibrationDue.technician}}</td>
    <td>{{calibrationDue.customer}}</td>
    <td>{{calibrationDue.vehicleManufacturer}}</td>
</tr>

This is pre-compiled markup. The compiled, rendered markup looks something like this (again trimmed for simplicity);

<tr _ngcontent-dqf-10="" class="pointer">
    <td _ngcontent-dqf-10=""></td>
    <td _ngcontent-dqf-10="">Sep 29, 2014</td>
    <td _ngcontent-dqf-10="">Sep 29, 2016</td>
    <td _ngcontent-dqf-10="">AA11AA</td>
    <td _ngcontent-dqf-10="">John Smith</td>
    <td _ngcontent-dqf-10="">John Smith Transport</td>
    <td _ngcontent-dqf-10="">Ford</td>
</tr>

Notice this rather auto-generated looking attribute that has been added to the markup? Well, it was auto-generated by Angular. The same attribute was also injected into the CSS. Why? to scope the CSS, to prevent it from having any effect on any other aspect of the site outside of the component itself. Any CSS you write in your CSS file, which is referenced by a component, cannot affect any other component or any other part of the site. The styles only affect the component itself. This is tremendously powerful and will result componentized CSS, but CSS that effectively does not cascade.

Angular 1.5+

Components were introduced in Angular 1.5 to help ease the transition (the upgrade path) from Angular 1 to Angular 2. If you are writing Angular 1 code currently and are looking to migrate to Angular 2 in the future, then consider re-writing your existing controllers into components to make your migration simpler in the future.

Dependency injection

Dependency injection in Angular is similar, in my experience, to dependency injection in many other languages/frameworks. Angular takes over managing the lifecycle of a components (or services) dependencies, and dependencies of those dependencies.

When you need to use a dependency, a service for example, you inject it into your component through the constructor. Dependency injection example;

import { Component, OnInit } from '@angular/core';
import { TodoStore, Todo } from '../services/todo.service';

@Component({
  selector: 'app-footer',
  template: require('./footer.component.html')
})
export class FooterComponent implements OnInit {
  constructor(public todoStore: TodoStore) {
  }
}

In the above example, our component needs to ues the TodoStore. Rather than creating a new instance of it inside the constructor, we add it as a parameter to our constructor. When Angular initialises our component, it looks at these parameters, finds an instance, then supplies it to the component.

Dependency injection in Angular is hierarchical. When the component needs a dependency, Angular looks to the components ancestors (parents, grandparents etc) until an instance is found. Depending on how you construct you application, dependencies can be (and probably will be) singletons. However, as dependency injection in Angular is hierarchical, it is possible to have multiple instances of the same service. When dependencies are defined at the “root level” of the application, the service will always be a singleton.

Angular takes care of initialising the dependency, and the dependencies of the dependency, so you only need to worry about using the dependency and not worry about managing it.

In the above code example, we are “referencing” each dependency using its type, therefore we don’t have to concern ourselves with making our code “minification safe”. In Angular 1, we define all our dependencies in a string array ($inject) so that Angular knows the names of each dependency at run time even after the code has been mangled. This step is no longer necessary.

Why?

Why would you want to handle dependencies in this way? Code complexity is reduced, and we can make our unit tests simpler. How? When using testing we can tell Angular to inject mock versions of our dependencies, to speed up the tests and ensure we’re only testing our own code and not Angular itself.

If you inject HttpClient into a service, for example, you would not want to make real HTTP requests to the server when running your tests. Instead, you inject a mock version of the HTTP client and simulate the request/response, for faster, consistent results.

Interpolation

Perhaps the most familiar concept in Angular, interpolation. Interpolation is the means of evaluating expressions, and displaying the results.

Take the following example;

<div class="view">
  <input class="toggle" type="checkbox" (click)="toggleCompletion(todo)" [checked]="todo.completed">
  <label (dblclick)="editTodo(todo)">{{todo.title}}</label>
  <button class="destroy" (click)="remove(todo)"></button>
</div>

The interpolation code is on line 4, {{todo.title}}. There is an object on the component, called todo. The object is a complex object, so it has many properties (and functions). In this case, we want to display the title of the todo to the user. Angular looks at this expression, determines the value of todo.title and renders it on the view. Whenever the value changes, that change is evaluated and displayed automatically.

You can display the results of practically any expression. Take another example; {{2+2}}. The result is 4, so 4 will be displayed on the view.

It is also permitted to invoke functions in interpolation expressions. The following code is perfectly valid;

{{ getTheCurrentDate() }}

As long as the component has a function called getTheCurrentDate, Angular will invoke it and display the result. You should avoid calling functions when possible as Angular will evaluate them more frequently than you expect, which can hurt performance when the functions do a lot of work. Instead, favour properties that do not change frequently.

Angular has a dependency on another open source project, called Zone.js. Zone.js handles change detection, and informs Angular when changes occur. Talking about Zone.js is out of scope of this post.

Pipes

Pipes are usually used in conjunction with interpolation. Pipes, known as filters in Angular 1, are used to format data.

For example;

<div>
    {{todoStore.todos | json}}
</div>

The above code takes the array of todos, and converts it to a string and displays that result in the view.

The following are pipes built in to Angular;
* Async – Automatically subscribe to observables, which are used extensive in Angular (Angular has a dependency on RxJS).
* Date – Used to format a date object. For example; Sunday 21st August 2016.
* Percent – Used to display a number as a percentage, can pass in the number of decimal places to show.
* JSON – Used to “toString” JavaScript objects
* Currency – Format numbers as currencies ($10.99 or £10.99)

Notice there is no OrderBy pipe in the list, like there was in Angular 1. That is because ordering was a particular pain point in Angular 1. Because of the way that Angular 1 detected changes, the ordering would often occur multiple times, which when working with large data sets killed performance. The Angular team have excluded the OrderBy pipe in favour of ordering being done by your code, within the component or service.

There are some other less important pipes, but generally there is significantly less built in pipes than in previous versions. This was a deliberate choice to keep the code base lean and clean.

Structural Directives

Structural directives directly affect the structure, or the elements within, the DOM (Document Object Model). Structural directives can add DOM elements, remove them and modify them.

The most commonly used structural directives are;

  • ngFor, which is used to loop through items in an array
  • ngIf, which adds/removes an element to/from the DOM depending on the result of an expression

The syntax for structural directives is different from the norm. Structural directives are prefixed with an asterisk (*). Take the following code;

<footer class="footer" *ngIf="todoStore.todos.length > 0">
    <span class="todo-count"><strong>{{todoStore.getRemaining().length}}</strong> {{todoStore.getRemaining().length == 1 ? 'item' : 'items'}} left</span>
    <button class="clear-completed" *ngIf="todoStore.getCompleted().length > 0" (click)="removeCompleted()">Clear completed</button>
</footer>

The structural directive is shown on line 1. *ngIf="todoStore.todos.length > 0". If the expression evaluates to true, then the footer is rendered, and all expressions within are rendered too. When the expression evaluates to false, the DOM element and all of its children are thrown away, removed from the DOM. This is to save Angular from having to evaluate code that the user is never going to see.

Below is an example of ngFor;

<ul class="todo-list">
    <li *ngFor="let todo of todoStore.todos">
        <app-todo [todo]="todo"></app-todo>   
    </li>
</ul>

On our component, we have a collection of todo, which contains zero, one or more items. For each todo in the collection, a new <li> is created. Angular scopes the <li> with the todo, so that any child element within the <li> can make use of the todo. In this example, the todo is passed to another component, called TodoComponent, whose responsibility is rendering single todo‘s to view.

In a nutshell, ngFor is a loop. Each iteration of the loop creates a new element which “knows” about the current item.

Attribute Directives

Next, we have Attribute Directives, which are responsible for changing the appearance of DOM elements. When using this square-brackets syntax, it “feels” like manipulating the DOM in JavaScript.

Consider the following code sample;

<div>
    <p [style.background]="backgroundColor">Hello, AO.com!</p>
</div>

The backgroundColor is a property on the component. In code, we can set the value of backgroundColor to be a color (yellow, or #ffff00 for example). The end result will be an inline style being applied, with the background property set to yellow.

Here is a screenshot on the compiled code at run time;

Angular 2 - Attribute directive run time example

You are not limited to manipulating the style of the element, you can change just about any property of the element.

Take another example;

<li *ngFor="let todo of todoStore.todos" [class.completed]="todo.completed" [class.editing]="todo.editing">
    <app-todo [todo]="todo"></app-todo>   
</li>

In this example, we are adding the CSS classes completed and editing to the element when todo.completed or todo.editing is true. Likewise, when false, the classes are removed.

Again, we could control the checked state of a Check Box (input field with a type of checkbox).

<input class="toggle" type="checkbox" (click)="toggleCompletion(todo)" [checked]="todo.completed">

When todo.completed is true, the Check Box is checked, otherwise, it is not checked.

Event Bindings

Event bindings are used to listen for user interactions, or events that get raised when the user interacts with the page or an element. Some events you may be interested in responding to; clicks, mouse moves, focus, blur, etc.

Event bindings are added to DOM elements and are denoted with brackets. Angular keeps an internal list of all the events it understands. If you try to listen for an event that it doesn’t map, Angular will look to your code instead (you can define your own custom events).

When an event occurs, typically a function on your component is invoked. You can pass arguments to the calling fuction, such as state, the event object, DOM elements, arbitrary values and more. It is also possible to pass state from one component to another using this mechanism.

Take the following example;

<label (dblclick)="editTodo(todo)">{{todo.title}}</label>

When the user double clicks on the label, the editTodo function is invoked. In this example, this element has a todo in scope, which is passed as an argument to the function.

Another example;

<input class="edit" *ngIf="todo.editing" [(ngModel)]="todo.title" (blur)="stopEditing(todo, todo.title)" (keyup.enter)="updateEditingTodo(todo, todo.title)"
  (keyup.escape)="cancelEditingTodo(todo)">

In this example, we are responding to the blur event (when the control loses focus) and key-presses (enter, escape) so we can perform an appropriate action when the user presses these keys on their keyboard.

Two way data binding

Two way data binding is primarily used when binding input controls to properties on the component. When using a two-way data binding, when a user interacts with a form (types data into a text field) that change is automatically reflected on the component. Likewise, if a property that is bound to an input field is changed in code (either by the component itself, or by something else, say an Observable being resolved) that change is reflected in the view immediately. Two way data binding is a mechanism for synchronising data between the view and the component.

To utilise two way data binding, you use ngModel. The syntax for correct use of ngModel is known as the banana in a box syntax (click the link for a full explanation as to how the name came about).

In reality, the banana in a box syntax is an amalgamation of and attribute directive and an event binding (and combination of the two). Banana in a box syntax is syntactic sugar for two mechanisms being used together, which helps you write less code.

Take the following example;

<input class="new-todo" placeholder="What needs to be done?" autofocus="" [(ngModel)]="newTodoText" (keyup.enter)="addTodo()">

When the value entered into the input field changes, the property newTodoText is automatically updated.

Now consider the long hand version of the same code;

<input class="new-todo" placeholder="What needs to be done?" autofocus="" [ngModel]="newTodoText" (ngModelChange)="newTodoText=$event" (keyup.enter)="addTodo()">

A separate event is needed to assign the new value to the property on the component ($event).

By combining the attribute directive and event binding, the code is more readable. The less code we can write, the easier our application will be to maintain over time.

Lifecycle Hooks

Lifecycle hooks can be thought of as events that get raised at key points during your components lifecycle. Lifecycle hooks are callback functions that are invoked by Angular when the component is in various transitional events.

Put another way, lifecycle hooks help you to execute code at the right times during the initialisation and destruction of your components.

Lets say your component needed to request some data from a HTTP endpoint. Where do you put code like that? In the constructor? No, ideally the constructor should be kept as clean as possible and should only initialise variables at the most. Having your constructor do a bunch of work will probably make your application run more slowly. Ideally what you need is a “load event”. Lifecycle hooks provide this. Lifecycle hooks help you execute code at the right time.

The most commonly used lifecycle hooks;
* ngOnInit: The “load event”
* ngDoCheck: Raised when Angular is running its internal change detection
* ngAfterViewInit: Raised when the component view has finished initialising
* ngOnDestroy: Called when the class is being destroyed/cleaned up

Side note; TypeScript has a construct called interfaces. If you come from a .NET background, interfaces in TypeScript are the same as what you already know. For everybody else, interfaces can be best thought of as “contracts”, which promise that the class that implements the interface also implements all the properties/functions defined on the interface. If a class implements an interface, and that interface has a function defined called ngOnInit, then the compiler can guarantee that function has been implemented on the class. (If not, a compile time error is emitted). Angular exposes an interface, called OnInit, that has a single function defined, called ngOnInit. Implementing this interface is best practice, but not mandatory. Just having the function in your class is good enough.

Example usage:

import { Component, OnInit, Input } from '@angular/core';
import { TodoStore, Todo } from '../services/todo.service';

@Component({
  selector: 'app-todo',
  template: require('./todo.component.html')
})
export class TodoComponent implements OnInit {
  ngOnInit() {
      //"load" logic goes here
  }
}

Some time after the instance of the component has been created, Angular will invoke the ngOnInit function, assuming it exists, enabling you to run custom logic (and call that HTTP endpoint, if that is what you need to do).

Routing

Routing is how the user gets around your Angular application. Routing is navigation between views/components. State, in the form of parameters, can be passed between views and can be injected into your components. A route is a combination of a path and a component. Routes are referred to by their path in your markup using the routerLink attribute directive.

Example usage;

<a routerLink="home" routerLinkActive="active">Home</a> | <a routerLink="about" routerLinkActive="active">About</a>

The above code sample also shows the use of the routerLinkActive attribute directive. This directive applies a CSS class to the element it is applied to when that route is active. The routerLinkActive directive works in conjunction with the routerLink directive, so that when the route referenced by the directive is active, the custom CSS class (in this case, called active) is applied to the element. Typically, you would want to change the visual appearance of the DOM element to indicate to the user that they are on a particular page.

Routing in Angular has been on a roller-coaster ride of changes throughout the alpha, beta and release candidate (RC) phases. The current iteration of the router uses a hierarchical router configuration approach to define routes, child routes, and to enable deep linking. For the sake of simplicity, we won’t discuss hierarchical routing/deep linking in this post, but be aware that it can be achieved by having multiple route configuration files at different levels of your applications. Child routes are extensions of their parents route.

Router configuration

To define the main routes of the application, we create a RouterConfig object, which is an array of routes. Most routes consist of a path and component. Other routes can have additional properties, like wildcard routes, which decide what to do when the user navigates to a path that does not exist (using the redirectTo property).

Example usage;

import { RouterConfig } from '@angular/router';
import { HomeComponent } from './components/home/home.component';
import { AboutComponent } from './components/about/about.component';

export const routes: RouterConfig = [
    { path: '', redirectTo: 'home', pathMatch: 'full' },
    { path: 'home', component: HomeComponent },
    { path: 'about', component: AboutComponent },
    { path: '**', redirectTo: 'home' }
];

Here we have four routes defined;

  • Default route: No path is defined, so when the user hits the page with no route parameters, they are redirected to ‘home’ (defined next).
  • Home route: Displays the HomeComponent.
  • About route: Displays the AboutComponent.
  • Wildcard route (**): When the route is not recognised, the user is redirected to the ‘home’ route. This is a catch-all.

The RouterConfig object is then referred to in the applications bootstrapper (loads the application and its component parts, called bootstrap).

Example usage (some code omitted for brevity);

import { provideRouter } from '@angular/router';
import { routes } from './routes';

bootstrap(AppComponent, [
    ...HTTP_PROVIDERS,
    FormBuilder,
    TodoStore,
    provideRouter(routes)
]);

The provideRouter function is exposed by the Angular router, and takes the RouterConfig object we just created.

More router directives

Angular also helps control navigation with several additional directives.

  • routerOutlet: Tells Angular where to put the view/component (used within the application shell, typically the AppComponent).
  • CanActivate: Allows navigation to be cancelled (useful for restricting access to certain pages under certain circumstances, like trying to access a page when the user is not logged in).
  • CanDeactivate: Runs before the route is changed, and can also cancel navigation (useful when, for example, prompting the user to save changes they have made to a form).

Angular does not “just know” about these directives, as everything router related lives within its own module. You must import the directives into your AppComponent‘s directives array;

import { Component } from '@angular/core';
import { ROUTER_DIRECTIVES } from '@angular/router';

@Component({
    selector: 'app',
    directives: [...ROUTER_DIRECTIVES],
    template: require('./app.component.html'),
    styleUrls: ['./app.component.css']
})
export class AppComponent {

}

The ROUTER_DIRECTIVES constant is a shortcut (an array, which includes all the directives previously discussed) to keep the code a bit cleaner.

Services

To end on a lighter note, services a reasonably straightforward in Angular. Services are classes that have the @Injectable decorator applied to them. The @Injectable decorator tells Angular that the class can be injected into components/directives/other services etc.

Services are used to share and abstract common functionality between one or more components. Services can help reduce code complexity and duplication. Depending on the configuration of your application, (remember the hierarchical dependency injection?), services can be singletons and maintain state over the lifetime of the application. Services can also have their own dependencies, which is handled the same way as how dependencies for your components are handled.

Example usage;

@Injectable()
export class TodoStore {
    //Implementation omitted   
}

I like to use services to add additional abstraction to some built in Angular services. Why? If the Angular API changes (and it has changed a bunch in the past), I have a single place where I have to make changes and get back up and running quicker.

Summary

Angular 2 is an opinionated web application framework for developing single page applications (SPA’s), and is actively developed by Google. Angular 2 is a move away from the original framework, it introduces and syntax’s and a “new way of doing things”. Important problems with past versions have been overcome (change detection/dirty checking was a major flaw of Angular 1) and the framework is taking a new direction. Whilst it is possible to write Angular 2 code in many ways, the preferred approach is to use TypeScript. There is a learning curve involved, the tooling especially is very much in its infancy, but once over the initial hump Angular 2 can be a fantastic framework when used in the manner it was intended for.

Angular 2 server side paging using ng2-pagination

Angular 2 is not quite out of beta yet (Beta 12 at the time of writing) but I’m in the full flow of developing with it for production use. A common feature, for good or bad, is to have lists/tables of data that the user can navigate through page by page, or even filter, to help find something useful.

Angular 2 doesn’t come with any out of the box functionality to support this, so we have to implement it ourselves. And of course what the means today is to use a third party package!

To make this happen, we will utilise n2-pagination, a great plugin, and Web API.

I’ve chosen Web API because that is what I’m using in my production app, but you could easily use ExpressJS or (insert your favourite RESTful framework here).

Checklist

Here is a checklist of what we will do to make this work;

  • Create a new Web API project (you could very easily use an existing project)
  • Enable CORS, as we will use using a seperate development server for the Angular 2 project
  • Download the Angular 2 quick start, ng2-pagination and connect the dots
  • Expose some sample data for testing

I will try to stick with this order.

Web API (for the back end)

Open up Visual Studio (free version here) and create a new Web API project. I prefer to create an Empty project and add Web API.

Add a new controller, called DataController and add the following code;

public class DataModel
{
    public int Id { get; set; }
    public string Text { get; set; }
}

[RoutePrefix("api/data")]
public class DataController : ApiController
{
    private readonly List<DataModel> _data;

    public DataController()
    {
        _data = new List<DataModel>();

        for (var i = 0; i < 10000; i++)
        {
            _data.Add(new DataModel {Id = i + 1, Text = "Data Item " + (i + 1)});
        }
    }

    [HttpGet]
    [Route("{pageIndex:int}/{pageSize:int}")]
    public PagedResponse<DataModel> Get(int pageIndex, int pageSize)
    {
        return new PagedResponse<DataModel>(_data, pageIndex, pageSize);
    }
}

We don’t need to connect to a database to make this work, so we just dummy up 10,000 “items” and page through that instead. If you chose to use Entity Framework, the code is exactly the same, except you initialise a DbContext and query a Set instead.

PagedResponse

Add the following code;

public class PagedResponse<T>
{
    public PagedResponse(IEnumerable<T> data, int pageIndex, int pageSize)
    {
        Data = data.Skip((pageIndex - 1)*pageSize).Take(pageSize).ToList();
        Total = data.Count();
    }

    public int Total { get; set; }
    public ICollection<T> Data { get; set; }
}

PagedResponse exposes two properties. Total and Data. Total is the total number of records in the set. Data is the subset of data itself. We have to include the total number of items in the set so that ng2-pagination knows how many pages there are in total. It will then generate some links/buttons to enable the user to skip forward several pages at once (or as many as required).

Enable CORS (Cross Origin Resource Sharing)

To enable communication between our client and server, we need to enable Cross Origin Resource Sharing (CORS) as they will be (at least during development) running under different servers.

To enable CORS, first install the following package (using NuGet);

Microsoft.AspNet.WebApi.Cors

Now open up WebApiConfig.cs and add the following to the Register method;

var cors = new EnableCorsAttribute("*", "*", "*");
config.EnableCors(cors);
config.MessageHandlers.Add(new PreflightRequestsHandler());

And add a new nested class, as shown;

public class PreflightRequestsHandler : DelegatingHandler
{
    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        if (request.Headers.Contains("Origin") && request.Method.Method == "OPTIONS")
        {
            var response = new HttpResponseMessage {StatusCode = HttpStatusCode.OK};
            response.Headers.Add("Access-Control-Allow-Origin", "*");
            response.Headers.Add("Access-Control-Allow-Headers", "Origin, Content-Type, Accept, Authorization");
            response.Headers.Add("Access-Control-Allow-Methods", "*");
            var tsc = new TaskCompletionSource<HttpResponseMessage>();
            tsc.SetResult(response);
            return tsc.Task;
        }
        return base.SendAsync(request, cancellationToken);
    }
}

Now when Angular makes a request for data, it will send an OPTIONS header first to check access. This request will be intercepted above and will reply with Access-Control-Allow-Origin header with value any (represented with an asterisk).

Format JSON response

If, like me, you hate Pascal Case JavaScript (ThisIsPascalCase), you will want to add the following code to your Application_Start method;

var formatters = GlobalConfiguration.Configuration.Formatters;
var jsonFormatter = formatters.JsonFormatter;
var settings = jsonFormatter.SerializerSettings;
settings.Formatting = Formatting.Indented;
settings.ContractResolver = new CamelCasePropertyNamesContractResolver();

Now lets set up the front end.

Front-end Angular 2 and ng2-pagination

If you head over the to Angular 2 quickstart, you will see there is a link to download the quick start source code. Go ahead and do that.

I’ll wait here.

Ok you’re done? Lets continue.

Install ng2-pagination and optionally bootstrap and jquery if you want this to look pretty. Skip those two if you don’t mind.

npm install --save-dev ng2-pagination bootstrap jquery

Open up index.html and add the following scripts to the header;

<script src="node_modules/angular2/bundles/http.dev.js"></script>
<script src="node_modules/ng2-pagination/dist/ng2-pagination-bundle.js"></script>

<script src="node_modules/jquery/dist/jquery.js"></script>
<script src="node_modules/bootstrap/dist/js/bootstrap.js"></script>

Also add a link to the bootstrap CSS file, if required.

<link rel="stylesheet" href="node_modules/bootstrap/dist/css/bootstrap.css">

Notice we pulled in Http? We will use that for querying our back-end.

Add a new file to the app folder, called app.component.html. We will use this instead of having all of our markup and TypeScript code in the same file.

ng2-pagination

Open app.component.ts, delete everything, and add the following code instead;

import {Component, OnInit} from 'angular2/core';
import {Http, HTTP_PROVIDERS} from 'angular2/http';
import {Observable} from 'rxjs/Rx';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/do';
import {PaginatePipe, PaginationService, PaginationControlsCmp, IPaginationInstance} from 'ng2-pagination';

export interface PagedResponse<T> {
    total: number;
    data: T[];
}

export interface DataModel {
    id: number;
    data: string;
}

@Component({
    selector: 'my-app',
    templateUrl: './app/app.component.html',
    providers: [HTTP_PROVIDERS, PaginationService],
    directives: [PaginationControlsCmp],
    pipes: [PaginatePipe]
})
export class AppComponent implements OnInit {
    private _data: Observable<DataModel[]>;
    private _page: number = 1;
    private _total: number;

    constructor(private _http: Http) {

    }
}

A quick walk-through of what I’ve changed;

  • Removed inline HTML and linked to the app.component.html file you created earlier. (This leads to cleaner seperation of concerns).
  • Imported Observable, Map, and Do from RX.js. This will enable us to write cleaner async code without having to rely on promises.
  • Imported a couple of class from angular2/http so that we can use the native Http client, add added HTTP_PROVIDERS as a provider.
  • Imported various objects required by ng2-pagination, and added to providers, directives and pipes so we can access them through our view (which we will create later).
  • Defined two interfaces, one called PagedResponse<T> and DataModel. You may notice these are identical to those we created in our Web API project.
  • Add some variables, we will discuss shortly.

We’ve got the basics in place that we need to call our data service and pass the data over to ng2-pagination. Now lets actually implement that process.

Retrieving data using Angular 2 Http

Eagle eyed readers may have noticed that I’ve pulled in and implemented the OnInit method, but not implemented the ngOnInit method yet.

Add the following method;

ngOnInit() {
    this.getPage(1);
}

When the page loads and is initialised, we want to automatically grab the first page of data. The above method will make that happen.

Note: If you are unfamiliar with ngOnInit, please read this helpful documentation on lifecycle hooks.

Now add the following code;

getPage(page: number) {
this._data = this._http.get("http://localhost:52472/api/data/" + page + "/10")
    .do((res: any) => {
        this._total = res.json().total;
        this._page = page;
    })
    .map((res: any) => res.json().data);
}

The above method does the following;

  • Calls out to our Web API (you may need to change the port number depending on your set up)
  • Passes in two values, the first being the current page number, the second being the number of results to retrieve
  • Stores a reference to the _data variable. Once the request is complete, do is executed.
  • Do is a function (an arrow function in this case) that is executed for each item in the collection received from the server. We’ve set up our Web API method to return a single object, of type PagedResponse, so this method will only be executed once. We take this opportunity to update the current page (which is the same as the page number passed into the method in the first place) and the _total variable, which stores the total number of items in the entire set (not just the paged number).
  • Map is then used to pull the data from the response and convert it to JSON. The way that RX.js works is that an event will be emitted to notify that the collection has changed.

Implement the view

Open app.component.html and add the following code;

<div class="container">
    <table class="table table-striped table-hover">
        <thead>
            <tr>
                <th>Id</th>
                <th>Text</th>
            </tr>
        </thead>
        <tbody>
            <tr *ngFor="#item of _data | async | paginate: { id: 'server', itemsPerPage: 10, currentPage: _page, totalItems: _total }">
                <td>{{item.id}}</td>
                <td>{{item.text}}</td>
            </tr>
        </tbody>
    </table>    
    <pagination-controls (pageChange)="getPage($event)" id="server"></pagination-controls>
</div>

There are a few key points on interest here;

  • On our repeater (*ngFor), we’ve used the async pipe. Under the hood, Angular subscribes to the Observable we pass to it and resolves the value automatically (asynchronously) when it becomes available.
  • We use the paginate pipe, and pass in an object containing the current page and total number of pages so ng2-pagination can render itself properly.
  • Add the pagination-controls directive, which calls back to our getPage function when the user clicks a page number that they are not currently on.

As we know the current page, and the number of items per page, we can efficiently pass this to the Web API to only retrieve data specific data.

So, why bother?

Some benefits;

  • Potentially reduce initial page load time, because less data has to be retrieved from the database, serialized and transferred over.
  • Reduced memory usage on the client. All 10,000 records would have to be held in memory!
  • Reduced processing time, as only the paged data is stored in memory, there are a lot less records to iterate through!

Drawbacks;

  • Lots of small requests for data could reduce server performance (due to chat. Using an effective caching strategy is key here.
  • User experience could be degegrated. If the server is slow to respond, the client may appear to be slow and could frustrate the user.

Summary

Using ng2-pagination, and with help from RX.js, we can easily add pagination to our pages. Doing so has the potential to reduce server load and initial page render time, and thus can result in a better user experience. A good caching strategy and server response times are important considerations when going to production.

TypeScript beginners guide

TypeScript is a tool that enables you to write better JavaScript. You may have heard that TypeScript is a superset of JavaScript, but what does that mean? TypeScript is JavaScript. If you know JavaScript already, then you already know JavaScript. You can convert an existing JavaScript file to TypeScript simply by changing the file extension. TypeScript has a very low barrier to entry (you can easily write it using Notepad) and has a small learning curve.

TypeScript has a transpiler, called tsc which transforms (compiles, if you like) your code from TypeScript to JavaScript. If you use any TypeScript paradigms, then your code cannot be understood directly by a JavaScript execution engine (V8 for example). You can, however, enable source maps and debug your TypeScript code directly.

Developers: “Why should I bother using TypeScript?”

When I talk to developers about TypeScript, the first thing they ask me is “Why should I bother using TypeScript?” or “I already understand JavaScript and I’ve been using it for x years, so I don’t feel the need to use it…”.

This is a great platform to explain to people why they should use TypeScript. Not because I’m on some personal mission or because I get paid by Microsoft (I don’t, but that would be awesome by the way) … it is because TypeScript can genuinely help developers write better code.

TypeScript enables developers to write more robust code

TypeScript provides several out of the box features that enable you to write more robust JavaScript;

1. Static typing

Properties, fields, function parameters and more can be decorated (sprinkled) with type declarations, which act as hints to the compiler and ultimately result in compile time type checking.

You can start very simply, by, say, adding a string type to a function parameter.

function print(message:string) {
    //Console log message here
}

This will ensure that any calling method passes a string value as a parameter. This means that should you attempt to pass, for example, a number you will get a compile time error.

If you think type checking can be a hindrance to the dynamic nature of JavaScript, read on.

2. TypeScript is optional, and it takes a back seat

Unlike most other programming paradigms, TypeScript is completely optional. If there is a feature you don’t like, you don’t have to use it. In fact, you can write 100% pure vanilla JavaScript inside a .ts file and never include any TypeScript paradigms and everything will work just fine. If you do encounter compile time errors, TypeScript will still emit your compiled JavaScript… you are not forced to fix the compilation error, unlike other compiled languages like C++ or C# for example.

In TypeScript 1.5+ there is a flag that stops compilation in the event that you encounter an error, should you choose to utilize this feature.

3. TypeScript is free, open source

Not only is TypeScript completely free and open source (even for commercial development), but there is also tooling for all the main operating systems (Linux, Mac, Windows) and is not just limited to the Microsoft stack. You can get TypeScript via NPM, NuGet, or you can download it from GitHub.

4. TypeScript enables developers to write modern JavaScript

Good developers want to use the latest iteration of their tools. They use these tools everyday, so keeping up to date makes sense.

The single biggest frustration for web developers who write JavaScript is cross browser support (is your company still supporting IE8?). TypeScript enables developers to write code against emerging standards whilst maintaining backwards compatibility. TypeScript is technically a transpiler and not a compiler, and it has a bunch of useful transformations to make this possible.

It is fair to say that the ECMAScript standard (the standard from which JavaScript ultimately derives) hasn’t evolved much over the last decade. There has been incremental updates, yes, but there has been a long gap between ES5 and ES6 (about 6 years to be precise). That’s all changed now, as the TC39 committee have committed to releasing revised standards on a yearly basis. In fact, officially, the ES6 standard has been renamed to ES2015, ES7 has been renamed to ES2016, and there will be yearly releases going forward. TypeScript enables developers to utilise these new standards because it provides transformations for many of them.

Example;
TypeScript 1.5 transforms the following ES6 string interpolation code;

var name = "Jon Preece";
var a = "Hello, ${name}";

to ES5 friendly string concatenation;

var name = "Jon Preece";
var a = "Hello, " + name;

Yes, you can use most ES6 features knowing with 100% confidence that the emitted code is widely supported by all decent browsers (IE 7+ at least).

In the interest of fairness, this isn’t true for all ES6 features. For example Promises must be supported natively by the browser (or polyfilled), there are many transformations available… resulting in a lot of developer feel-good. Check out my post Using ES6 features with TypeScript for more transformations.

Ultimately, however, I always recommend to developers that they use the right tools for the job, and that they use the tools that they themselves are most comfortable using. I recommend the same for you. Take the time to evaluate TypeScript, experiment with it, and see if it can be introduced into your daily development workflow. If you are developing a greenfield project, why not introduce it from the beginning?…after all, TypeScript really comes into it’s own when used in a medium to large team environment.

The Basics

Converting a JavaScript file to TypeScript

As briefly mentioned, you can convert a JavaScript file to TypeScript by changing the file extension from .js to .ts. You will have to call upon the TypeScript compiler (known herein as tsc) to emit the resulting JavaScript file for you.

There are several approaches to using tsc depending on your operating system, IDE, and preferences. My operating system of choice, for example is Windows 8.1 with VS Code. You, however, might use Sublime Text on a Mac or Vim on Ubuntu (these are just examples).

Add type declarations to function parameters

The simplest feature of TypeScript to use out of the box, and arguably the best feature, is type declarations, or static typing. You declare the type of a function parameter using the following syntax;

function print(message:string) {
    //Console log message here
}

This is the same code as shown earlier. We want to log a message to the console window, or display a message to the user, or whatever the case is. It’s reasonable to assume that the message will be a sequence or alphanumeric characters… a string.

It might not make any sense to do the following;

//Print '123' to the screen
print(123);

//Print this object to the screen
print({message: "abc" });

The result of calling the function in this matter is unpredictable a best, and at worst could result in an error in your application. By applying the type declaration to the parameter, we can get a warning at compile time that there is a problem.

It is worth mentioning that type declarations are specific to TypeScript, nothing related to the type declaration will be emitted into the final JavaScript. They are a compile time hint.

Type declarations everywhere

Type declarations are not just limited to function parameters. You can include them on properties, fields, and the return value for a function too!

There are other places, like Type Declaration files, but that is out of the scope of this post.

The ‘any’ type

Sometimes, a type isn’t known until runtime. In situations where type isn’t known, you could use the any type;

print(message: any) : string { }

This tells TSC that type is “unknown” and that static analysis is not required or appropriate.

Classes and Modules

By default, TypeScript does not use any sort of Asynchronous Module Defition (AMD) pattern. You may be familiar with RequireJS et al, but the default pattern is the IIFE pattern (you can change this if necessary).

Modules help with code organisation and reduce global scope pollution. Take the following code;

module Printing {
    class Printer {
        constructor(private startingValue: number) {

        }
        print(message: string): string {
            //Do something

            return "";
        }
    }
}

TypeScript will generate a root object, named Printing. This object will be added to the global scope. This is the module, and you can have as many modules in your application as you like.

Anything nested inside a module will be added to it as an object. So in this case, the Printer object will be added to the Printing object. This is great because now only 1 object has been added to the global scope, instead of two (reducing conflicts with your code and other external dependencies).

Constructors

Constructors are a feature of ES6, called when an object is instantiated. You can include your set up logic here for the specific instance. You can also pass values to the constructor and get full IntelliSense support;

module Printing {
    class Printer {
        private startingValue: number;

        constructor(startingValue : number) {
            this.startingValue = startingValue;
        }
    }
}

Understanding constructor parameters

Constructor parameters are slightly different compared to other programming languages. In the above example, we have a private field named startingValue, and we set it’s value to whatever the value of the startingValue constructor parameter is;

this.startingValue = startingValue

This is unnecessary in TypeScript… TypeScript provides some syntactic sugar to sweeten this up.

The following code is valid TypeScript;

module Printing {
    class Printer {
        constructor(private startingValue : number) {

        }
    }
}

This is valid because under the hood TypeScript created a variable on the class with the name startingValue inside the constructor and assigned the value automatically. Unless you explicitly apply an access modifier to the parameter, it is public. You can add the private access modified to make that parameter only accessible with the class itself and not externally.

Summary

TypeScript is a tool that enables developers to write more robust, scalable, maintainable, team friendly JavaScript code. Large JavaScript applications tend to descend into a spaghetti, landmine-ridden battlefield that can only be maintained by a single developer who understands all the moving parts. With TypeScript, those days are over. Getting started with TypeScript is as simple as renaming a file, sprinkling on a few type annotations, and reaching out to tsc via the command-line or using your editor of choice (on the operating system of your choice!).

Writing AngularJS 1.x with TypeScript

AngularJS 1.x is a front end JavaScript framework that has gained huge traction and popularity in the development community. AngularJS greatly simplifies previously hard tasks like two-way data binding, templating, the MVC design pattern, despendency injection and more. Using TypeScript, we can create more robust and scalable AngularJS code to deliver the ultimate user experience whilst avoiding the traditional spaghetti code nightmare that JavaScript applications can often descend into.

AngularJS version 1.x is written in JavaScript. Its successor, Angular 2.x, is written using TypeScript. It was originally going to be written in Google’s propriety language AtScript, but the teams have merged the projects and are now working together on TypeScript.

All the code for this project is available to view on GitHub.  There is also a demo project on GitHub pages.

Note: This tutorial assumes you have some knowledge of Angular 1.x.

Note: This tutorial tries to stay editor independent, meaning the concepts apply to TypeScript specifically and not to an editor. When necessary, screenshots showing relevant information will be of VS Code. VS Code is a free, cross platform editor hat has excellent built in TypeScript support.

Type Declaration Files

Also known as “Type Definition Files”, these are files that have the extension .d.ts and contain all the information to, for lack of a better word, describe the structure of a JavaScript library.

“When using an external JavaScript library, or new host API, you’ll need to use a declaration file (.d.ts) to describe the shape of that library.”

Referenced from the TypeScript handbook.

You will need to reference the AngularJS type declaration files for AngularJS to get full auto-completion/intelli-sense support and to be able to fully ultilise TypeScript’s static typing functionality.

Initial Setup

We will develop a simple application based on the HaveIBeenPwned API.  We’ll cover the specifics of that shortly.

Task runner

First, there’s some configuration in VS Code that we need to do. This same concept applies regardless of your editor.

  1. Create a new directory somewhere, say on your desktop, called AngularJSAndTypeScript101.
  2. Open VS Code, click File > Open Folder… and point to the directory you just created.
  3. Click File > New File… and add the following code…
{
    "compilerOptions": {
        "module": "none",
        "target": "ES5"
    },
    "files": [
        "app.ts"
    ]
}

Now you need to create a task runner. A task runner will transpile your TypeScript each time you run the task.

  1. In VS Code, add a new file called ‘app.ts’
  2. Press Ctrl+Shift+B to trigger the task runner. VS Code will bring up a little message at the top of the screen telling you that there is no task runner configured. Click the “Configure Task Runner” button. VS Code will create a tasks.json file automatically for you.
  3. Change the args property from HelloWorld.ts to app.ts. We will revisit this later to take a wildcard selector.

Open your app.ts file, and add the following code;

class Hello{
    constructor() {
        console.log("Hello!");
    }
}

Press Ctrl+Shift+B to kick off the build. Once complete (it takes < 1 second on a half decent machine) you will notice a new file has been added to the project, called app.js.

Switch to split view by clicking the little side by side window icon on the top right hand side of the screen, and in the right hand pane open the newly generated app.js file. This is optional of course, if you don’t care about the compiled JavaScript, that’s absolutely fine. Sometimes it is nice to be able to see it.

Compile on save

If you have Node.JS tools installed, and you don’t want the hassle of pressing Ctrl+Shift+B every single time you want to compile, you can do the following to enable compile on save;

  1. Open a Node.js command prompt and change directory to the root folder for your project
  2. Type the following command;
tsc -w app.ts

TypeScript will listen for changes to your file, and transpile it automatically every time you make a change (and save).

In addition, VS Code has an Auto-Save feature.  To enable it, click File > Auto Save.  If you have the TypeScript file and JavaScript files open side by side, the JavaScript file will periodically update without the need to manually save changes.

Adding AngularJS

Next, we need to add AngularJS to our project. You can do this using either Node Package Manager (NPM) or manually by download the appropriate files and adding them into your project folder. VS Code is still pretty young at this point (July 2015) and support for pulling in packages is non-existent.

Using NPM and Bower

If you don’t already have bower, a client side package manager, installed you can use the following command from a Node.js command prompt;

npm install -g bower

This will install bower globally on your machine. Now add a new file to your project called bower.json and add the following configuration:

{
    "name": "AngularTypeScript101",
    "version": "1.0.0",
    "dependencies": {
        "angular": "~1.4.0",
        "angular-route": "~1.4.0"
    }
}

This will bring in version 1.4.0 of AngularJS. Feel free to change this to use whatever the current version of Angular 1.x is.

Now run the following command, again from your Node.js command prompt;

bower install

This will download the packages and add them to your project folder under a sub directory called bower_components.

Using Visual Studio NuGet

If you happen to be following along using Visual Studio (full fat), you can easily install these packages using the following commands; (which you run via the Package Manager Console PowerShell window.

install-package angularjs.core
install-package angularjs.route

You can use the same mechanism to easily update the packages too (using the update-package command).

Manually

You can, of course, download Angular manually and add it to your project. You will find the latest version on the AngularJS website.

You will probably find it easier to maintain your packages over time using Bower.

Adding the type declaration files

Thankfully TypeScript has a built in mechanism for adding type declaration files to your project. This is done using the TypeScript Definition Manager.

Using the TypeScript Definition Manager

You install the TypeScript definition manager using NPM. Open a Node.js command prompt and enter the following;

npm install -g tsd

This will install the TypeScript definition manager globally.

The TypeScript declaration files are fully open source and can be found on the Definitely Typed GitHub repo. The AngularJS declaration files can be installed using the following command;

tsd install angular
tsd install angular-route

This will create a new directory called typings with a sub directory called angularjs. Within will be the two Angular declaration files you just installed.  As AngularJS has a dependency on jqLite, the declaration files for jQuery will also be pulled in.

Using NuGet

You can install the declaration files by running the following command in the Package Manager Console PowerShell window.

Install-Package angularjs.TypeScript.DefinitelyTyped

Manually

You could of course just download the declaration files directly from the GitHub repository and copy them into the correct folder. (typings/angularjs)

Referencing the declaration files

Now that you have installed the declaration files for Angular, flip back to your app.ts file and add the following code;

class Hello{
    constructor() {
        angular.module("HelloApp", []);
    }
}

No matter which technique you use to compile your JavaScript, you will get the following error message; (I believe that support for this is going to be vastly improved in future versions of VS Code)

Cannot find name 'angular'

That’s fine. All we need to do is tell TypeScript about our declaration files by adding the following code to the very top of the code file;

/// <reference path="typings/angularjs/angular.d.ts" />
/// <reference path="typings/angularjs/angular-resource.d.ts" />

Many modern editors, including Visual Studio and Webstorm, don’t require this additional step because they’re smart enough to check for the existence of the typings sub folder.

Add the references, press Ctrl+Shift+B (or Save) to recompile and the error should go away.

Web Server

AngularJS, like most other JavaScript libraries, doesn’t work properly when viewed directly from the file system. If you open a file on your desktop, the path will be something like this;

file:///C:/Users/jon.preece/Desktop/AngularTypeScript101/index.html

Chrome, Firefox, and most other web browsers won’t allow you to consume other markup files due to security concerns (CORS). With that in mind, you will need some sort of web server to serve up the files so they can be previewed properly in the browser.

VS Code does not have a built in HTTP server, so we must use another mechanism. If you’re using Visual Studio (full fat), then you can use the built in server and skip this step.

Http-Server

There is a very nice HTTP server on NPM that is more than sufficient for our needs. To install it, run the following command from a Node.js command prompt;

npm install -g http-server

This will install a simple HTTP server globally on your machine. To, run the server change directory (cd) to your root project folder and type the following command;

http-server -o --cors

There are lots of options you can pass in to customize the behaviour, but the default configuration will be enough for us.

The default address is http://localhost:8080.

IIS

You can configure IIS to host the site for you. To do so, follow these steps;

  1. Open the Internet Information Services (IIS) manager (inetmgr.exe)
  2. Add a new site, call it “HaveIBeenPwnd”
  3. Point the physical path to your project folder.
  4. Enter the following host name: haveibeenpwnd.local
  5. Open your hosts file (C:\Windows\System32\Drivers\etc\hosts) in your favourite text editor (VS Code if you like!)
  6. Add the following line;

127.0.0.1 haveibeenpwnd.local

Open your web browser and point to haveibeenpwnd.local.

Sample Project

In order to demonstrate the concepts thoroughly, we are going to develop a simple project that utilizes the HaveIBeenPwned API. If you are not familiar with this service, HaveIBeenPwned is developed and maintained by developer security expert Troy Hunt. HaveIBeenPwned checks to see if your email address or username has been compromised in a data breach. The HaveIBeenPwned API is a way to access this wealth of information programmatically via a Restful endpoint.

The project shows how to write the following AngularJS concepts in TypeScript;

  • Controllers
  • Directives
  • Filters
  • Services
  • Routing

The sample project is certainly not feature complete. In fact, all the samples are about as simplistic as they can possibly be… but that’s intentional.

Style Guide

Whenever I write any AngularJS code, I always follow (with only minor deviation) the Angular JS Style Guide, which was written by John Papa. It is an excellent guide and I highly recommend that you check it out.

If you’ve never used a style guide before, just remember, a guide is exactly that… it is a guide. Use what bits make sense for your project.

Project Structure

The structure of the project is as follows;

/client
    /HaveIBeenPwned 
        /controllers
        /directives
        /filters
        /models
        /services
        /views
/content
    /css
/typings
    /angularjs
    /jquery
index.html
package.json
tsconfig.json

We will add in the appropriate files as we go along.

Referencing declaration files

At the time of writing, VS Code does not recognise the fact that you have added type declaration files to your project. I suspect that in the future this will be resolved, but for now you have to manually reference the typings files directly in your TypeScript files.

Type declaration files are referenced using a special triple forward slash (///) syntax;

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

VS Code will now load in these files and provide IntelliSense/auto-complete based on the declarations made in each file. If you are using Visual Studio, you can skip this step.

Note: It is out of the scope of this post to discuss how type declaration files work, we will cover this is a future post.

Note: Please ensure that every TypeScript file that you write for this project has these references at the top.

Modules

When not using any sort of AMD, the default pattern that TypeScript generates is the IIFE pattern. Take the following TypeScript code;

class App{
    "use strict";
}

TypeScript generates the following;

var App = (function () {
    function App() {
    }
    return App;
})();

This code is fine. It works. But there is one major problem. TypeScript has placed a variable on the global scope. A variable called App now exists on the window object. In our case, it is very unlikely that this would impact any other part of the application, but in larger projects with lots of scripts and external dependencies, this is a common problem. TypeScript introduces modules to help avoid this problem and also help with the organization of your code.

Usage;

module HaveIBeenPwned{
    "use strict";	
     class App{
				
    }
}

TypeScript generates the following;

var HaveIBeenPwned;
(function (HaveIBeenPwned) {
    "use strict";
    var App = (function () {
        function App() {
        }
        return App;
    })();
})(HaveIBeenPwned || (HaveIBeenPwned = {}));

A global object is still added to the window object, but now our App class is added as a property on the HaveIBeenPwned object. Everything wrapped inside a module with that name will be added as properties to it.

Example;

module HaveIBeenPwned{
    "use strict";
     class Routes {
		
    }
}

TypeScript generates the following code;

var HaveIBeenPwned;
(function (HaveIBeenPwned) {
    "use strict";
    var Routes = (function () {
        function Routes() {
        }
        return Routes;
    })();
})(HaveIBeenPwned || (HaveIBeenPwned = {}));

As the HaveIBeenPwned object already exists, the Routes object will simply be added to it.

Add a file called app.module.ts to the HaveIBeenPwned folder, and add the following;

module HaveIBeenPwned{
    "use strict";	

    angular
        .module("HaveIBeenPwned", ["ngRoute"]);
}

This will initialize the AngularJS app, and pull in the Routing module (ngRoute).

Point to take away: Modules help organise your code and stop the global scope from becoming polluted.

Dependency injection for functions

Routing is the perfect place to start leveraging TypeScript in our application. Routing configuration tells AngularJS where to find our views, and which controller to use for a specific path navigated to.

Routing is passed to AngularJS as configuration, using the config function.

Traditional AngularJS code;

angular
    .module("HaveIBeenPwned")
    .config(["$routeProvider", function($routeProvider) { /*Routing goes here*/ } ]);

The traditional JavaScript way is to pass a list of dependencies as a string array, then the final parameter is a function in which those dependencies are injected. This is primarily to support minification, so that dependencies can still be injected once all the variable names have been changed.  TypeScript enables us to write this type of code in a much cleaner fashion.

You might be aware that with AngularJS, you can directly inject dependencies into a function by attaching a property called $inject.

Example;

function routes(){
    
}
routes.$inject = ["$routeProvider"]

I’ve found that this is rarely used in practice…perhaps due to lack of knowledge of the feature or simply because most of the documentation shows how to use the traditional style shown above.

TypeScript lends itself well to using the $inject function.

Add a new file called app.route.ts to the HaveIBeenPwned directory, and add the following code;

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

module HaveIBeenPwned {
    "use strict";

    function routes($routeProvider: ng.route.IRouteProvider){
    }

    routes.$inject = ["$routeProvider"]

    angular
        .module("HaveIBeenPwned")
        .config(routes);
}

Most of this code should look familar to you. Technically, there is absolutely no reason why you can’t use the traditional AngularJS style for passing dependencies to a function, I just find this syntax is much cleaner.

Type declarations on function parameters

With this code we encounter the first usage of a type declaration;

function routes($routeProvider: ng.route.IRouteProvider){

First, take a look at the compiled output;

function routes($routeProvider) {

It’s important to note that the type declarations are a TypeScript specific feature. Type declarations are not a feature of JavaScript. Type declarations are there to provide IntelliSense/auto-complete support and code refactoring, such as renaming of variables.

All AngularJS declarations can be found in the ng namespace. In this case, we need the route provider to define our routing configuration. Routing is not part of the core AngularJS library, in fact it was split out into its own module named ngRoute. All declarations for routing can be found in the ng.route namespace.

Add the following code to the routes function. Please type the code rather than copy/paste it.

$routeProvider
    .when("/search", {
        templateUrl: "/client/HaveIBeenPwned/views/_search.html",
        controller: "SearchController",
        controllerAs: "vm"
    })
    .otherwise({
        redirectTo: "/search"
    });

You should immediately see the benefits now.

IntelliSense On Routing Provider

 

Not only do you get IntelliSense will full documentation, but you also get the added benefit of compile time checking;

Compile Time Checking

 

In this case I have provided the wrong number of arguments to the function… I get instant visual feedback on that.

Note: My code still compiled. Even though the code I wrote in the above examples was wrong, the JavaScript was still generated and I could call that in the browser (all be it, with unpredictable behaviour).

To complete the routing, add the following code to the routes function;

$routeProvider
    .when("/search", {
        templateUrl: "/client/HaveIBeenPwned/views/_search.html",
        controller: "SearchController",
        controllerAs: "vm"
    })
    .otherwise({
        redirectTo: "/search"
    });

Don’t worry about creating the views or controllers at this point. We will do that later.

Dependency injection for classes

Injecting dependencies into classes is slightly different. With functions, we inject dependencies by tacking on an $inject variable to the function.  With classes, we instead have a static variable with the same name.

Example;

static $inject = ["PwnedService"];

As with most other programming languages, static is not instance specific, it applies to all instances. The generated JavaScript we end up is the same code as was generated for functions.

Example;

SearchController.$inject = ["PwnedService"];

Add a new file to the controllers directory, named search.ts. This will eventually be used to call an AngularJS service, which will call out to the HaveIBeenPwned API and return the result.

module HaveIBeenPwned {
    class SearchController {
    static $inject = ["PwnedService"];
        constructor(private pwnedService: IPwnedService) {
            
	}
    }    
    
    angular
       .module("HaveIBeenPwned")
       .controller("SearchController", SearchController);
}

Note: We don’t have a IPwnedService yet, we’ll get to that in a minute.  Ignore any compile time errors your editor might be giving you at this point.

Constructors

Constructors are a feature of ES6, called when an object is instantiated. Again, constructors work the same in JavaScript as they do in any other programming language.

In the interest of cross-browser support, TypeScript generates a function with the same name as the containing function to indicate that it’s a constructor.

Example of an empty constructor in TypeScript;

class SearchController {
    constructor() {
        //constructor logic	
    }
}

and the resulting JavaScript

var SearchController = (function () {
    function SearchController() {
        //constructor logic	
    }
    return SearchController;
})();

Again, constructors are now natively supported in ES6 so when targeting that version the code won’t be transpiled.

Understanding constructor parameters

Assume the following code;

constructor($http : ng.IHttpService) {  
}

If you wanted to reuse the $http variable in other functions in your class, you might be tempted to do the following;

private _httpService: ng.IHttpService;

constructor($http : ng.IHttpService) {
    this._httpService = $http;
}

You should understand that the act of assigning the constructor parameters to a private variable (like you might do in other languages) is redundant in TypeScript. Under the hood TypeScript does this for you.

The following code is valid TypeScript;

constructor($http : ng.IHttpService) {
    
}

someOtherFunction() {
    this.$http.get(...);   
}

This is valid because under the hood TypeScript created a variable on the class with the name $http inside the constructor and assigned the value automatically.

The transpiled JavaScript

var PwnedService = (function () {
    function PwnedService($http) {
        this.$http = $http;
    }
    ...
}

Unless you explicitly apply an access modifier to the parameter, it is public. You can add the private access modified to make that parameter only accessible with the class itself and not externally. I typically mark all my constructor parameters a private unless I need them to be accessible externally, although I’m not aware of any performance or other impact of not doing this.

Make objects visible to others using ‘Export’

The code shown in the previous example creates a controller called SearchController, using the ES6 class feature. By default, the class is not accessible to any other external objects.

SearchController Is Inaccessible

 

SearchController is not defined because it is not accessible.  It is desirable to expose certain objects so that they can be consumed in other places. Generally I only expose objects that have to be exposed, but there is no hard and fast rule on this and no performance impact that I’m aware of, other than a slightly busier namespace object.

To expose a class, interface, or function to other objects, use the export keyword.

export class SearchController {

This makes a subtle change to the generated code. This following line is added after the SearchController IIFE.

HaveIBeenPwned.SearchController = SearchController;

Now re-running the code in developer tools results in the following;

SearchController Is Accessible

 

Note: This is a transformation provided by TypeScript and there is not a comparable feature in ES6 at the time of writing (July 2015).

Interfaces

Interfaces are contracts that state that an object will contain the functions and properties defined therein.

Simple interface declaration;

module HaveIBeenPwned{
    export interface IPwnedService {
		
    }
}

Note that the above code results in zero JavaScript output. Why? Simple. JavaScript does not support interfaces or contracts of any kind. JavaScript is a dynamic language and properties/functions can be added to any object at any time. Interfaces are syntactic sugar provided by TypeScript to support IntelliSense/auto-complete and compile time checking.

Add the following function to the interface (we will discuss promises shortly);

check(address:string) : ng.IPromise<{}>;

An interface function has no implementation, that will be defined on the implementation class.

Naming conventions

The official TypeScript style guide clearly states that interface names shouldn’t be prefixed with I. I come from a C# background and I’m simply too stuck in my old ways to adhere to this recommendation, and I know a lot of folk feel the same. My advice to you, choose whatever naming convention makes the most sense to you, and stick with that.

Note also that I like to keep my interfaces and classes in the same physical file as the class that implements it (as long as it’s not too long). I recommend, again, that you pick an approach that works best for you, and then stick with that.

Working with interfaces

You can implement an interface on a class using the implements keyword as follows;

class PwnedService implements IPwnedService

Flesh out the class as follows;

module HaveIBeenPwned{	
    export interface IPwnedService {
	check(address:string) : ng.IPromise<{}>;
    }
	
    class PwnedService implements IPwnedService {
		
 	static $inject = ["$http"];
	constructor(private $http : ng.IHttpService) {			
	}
		
	check(address:string) : ng.IPromise<{}> {			
	}		
    }
	
    angular
	.module("HaveIBeenPwned")
    	.service("PwnedService", PwnedService);
}

If you add a property or a function to the interface, or change it, and forget to update the implementation class, you will get a compile time error.

You can also use interfaces with JSON. Take the following TypeScript example;

var a = <IMyInterface>{
  someValue: 'Hello'  
};

Instead of having to instantiate a class that implements the IMyInterface interface, you can exploit JavaScript’s dynamic nature and pass in a raw JSON object. Specifying the interface before the object definition is a hint to TypeScript of what you are doing. In return, you will get full IntelliSense/auto-complete when defining the object, as well as compile time checking for all usages of that object.

Finally, you can also derive interfaces from other interfaces. Interface inheritance if you like.

Example;

export interface IEnterKeyPressAttributes extends ng.IAttributes {
    ngEnter: string;   
}

The above example shows a new interface, that uses the extends keyword to derive from the ng.IAttributes interface. The IEnterKeyPressAttributes interface has all the same methods and properties as the ng.IAttributes interface, and can add its own too.

Promises

Promises are a new shiny feature in ES6. Unfortunately, promises need to be supported either natively by the browser or via a polyfill. AngularJS has promises baked right in to many components. You can use promises indirectly, via a common service such as $http, or you can create promises directly using $q.

Example;

class PwnedService {
    constructor($q : ng.IQService) {
    }
    
    check() : ng.IPromise<{}> {
        var defer = this.$q.defer();
        //Do something useful
        //Then call either defer.resolve() or defer.reject()        
        return defer.promise;   
    }   
}

Or using $http:

class PwnedService {
    constructor($http : ng.IHttpService) {        
    }
    
    check() : ng.IPromise<{}> {
        return this.$http.get("https://haveibeenpwned.com/api/v2/breachedaccount/" + address);    
    }   
}

In the interest of avoiding the promise anti-pattern, I tend to use promises through other components, rather than directly and just chain on callbacks.

Anyway, whichever technique you prefer, you will end up defining ng.IPromise<{}> as the return type for the parent function (see check method above).

Technically, in TypeScript world, this is wrong. I’ve basically said that the promise will return “an object” as yet to be determined. However, I know what the correct type is;

ng.IPromise<ng.IHttpPromiseCallbackArg<BreachedAccount[]>>

Why didn’t I just write that in the first place? I simply don’t like the use of nested generics. Sure I lose a little bit of IntelliSense and compile time checking, but this has never been an issue for me.

Calling a function that returns a promise

Flip back to the SearchController.ts file and add the following function;

private breachedAccounts : BreachedAccount[];

submit(address: string) {
    this.pwnedService.check(address).then((result : ng.IHttpPromiseCallbackArg<{}>) =>{
        this.breachedAccounts = result.data;
    });
}

There’s no magic here, the code is the same as what you would write in JavaScript. The only difference is that you get IntelliSense support on the result object.

The any type

Sometimes, a type isn’t known until runtime. This is especially true when calling a Web API back end. The response you get when an exception is thrown by the runtime (unhandled) is very different than an exception thrown by your code.

If your code is really broken, you might get a 500 response with a yellow screen of death.  The yellow screen of death is pure HTML markup only with on JSON representation.

A runtime exception object might look like this;

{
    ...
    "Exception": {
        "Message": "Object reference not set to an instance of an object."   
    }   
    ...
}

Also, your code might return the following ‘graceful’ exception when an error is encountered.

{
    ...
    "exception": {
        "message": "The request was malformed"   
    }   
}

The difference between these two responses. Casing. By default, the .NET runtime returns responses in Pascal Case. You have to jump through several hoops to get the response to return in Camel Case, a step all so often not done fully.

In situations where type isn’t known, use the any type;

submit(address: string) {
	this.pwnedService.check(address).then((result : ng.IHttpPromiseCallbackArg<{}>) =>{
		this.breachedAccounts = result.data;
	})
	.catch((reason : any) => {
		alert(reason.Message || reason.message);	
	});
}

This will put an end to any compile time nagging.

–noImplicitAny

In the above example, we have explicitly told TypeScript that reason does not have a type. With that in mind, do you think it’s equally valid to leave off the type declaration altogether? Absolutely, because the static typing in TypeScript is optional.

The following code is valid TypeScript;

submit(address: string) {
	this.pwnedService.check(address).then((result : ng.IHttpPromiseCallbackArg<BreachedAccount[]>) =>{
		this.breachedAccounts = result.data;
	})
	.catch((reason) => {
		alert(reason.Message || reason.message);	
	});
}

No type was given for reason. However, because the type is any is the type declaration files, it is still explicit.

Take the following code;

var y;

In this code there is no way that TypeScript can know what the type is, therefore it is implicitly any.

If you want to prevent implicit use of the any type, you can pass in the --noImplicitAny flag to the TypeScript compiler when you execute it.

tsc --noImplicitAny -w

Model classes

Add the following model class to the models folder;

module HaveIBeenPwned {
    export class BreachedAccount {
	Title: string;
	Name: string;
	Domain: string;
	BreachDate: string;
	AddedDate: string;
	PwnCount: number;
	Description: string;
	DataClasses: string[];
	IsVerified: boolean;
	LogoType: string;
    }
}

This class will be used to map the response from the HaveIBeenPwned api back to an object for strong typing and compile time support. This is the exact data as returned by the API, and it returns the properties in Pascal Case, so we will have to use that here (or write ugly mapping code, but I’d rather avoid that).

Search View

Add a new file to the views folder called _search.html. Add the following markup;

<form ng-submit="vm.submit(vm.emailAddress)">
    <div>
	<label>Enter your email address:
	    <input type="email" id="emailAddress" name="emailAddress" ng-model="vm.emailAddress" placeholder="[email protected]" ng-enter="vm.submit(vm.emailAddress)">
	</label>
    </div>
    <button type="submit">Check Now</button>
</form>
<table>
    <thead>
 	<tr></tr>
    </thead>
    <tbody>
	<tr ng-repeat="breachedAccount in vm.breachedAccounts">
	    <td>{{breachedAccount.Title}}. <div ng-bind-html="breachedAccount.Description | asHtml"></div></td>
	</tr>
    </tbody>
</table>

There are two things of particular interest here, the use of a custom AngularJS directive called ngEnter, and a custom filter called asHtml.

ngEnter directive usage;

<input type="email" id="emailAddress" name="emailAddress" ng-model="vm.emailAddress" placeholder="[email protected]" ng-enter="vm.submit(vm.emailAddress)">

asHtml filter usage;

<div ng-bind-html="breachedAccount.Description | asHtml"></div>

We will need to create both of these before we can continue.

Filters

Filters are defined as follows;

A filter formats the value of an expression for display to the user.

When we call out to the HaveIBeenPwned API, it will return an array of BreachedAccount to us. Each BreachedAccount will have a property called Description. This description is HTML markup that will contain links and other interesting stuff.

By default, AngularJS (rightly so) will encode the string to make it safe. The HTML markup will be rendered on the page, rather than added to the DOM and executed.

We want to override this default behaviour, and render the HTML instead. Generally speaking, I wouldn’t recommend this approach because of the security implications (injection of potentially dangerous script) but in this small contrived example, it is fine. And lets be honest, it is unlikely that Troy Hunt, the security guy, is going to have some malicious script sent to us. Of course, you should never take this for granted.

Anyway, add a file called asHtml.filter.ts to the filters directory. In terms of their behaviour, filters are much like the routing code we wrote earlier.

Add the following code;

module HaveIBeenPwned{
    "use strict";

    export function asHtml($sce : ng.ISCEService) {
	return (text : string) => {
		return $sce.trustAsHtml(text);
	}
    }
	
    angular
	.module("HaveIBeenPwned")
	.filter("asHtml", asHtml);
		
    asHtml.$inject = ["$sce"];
}

Filters are defined by calling the filter function, passing in the name of the function as a string, and a reference to the function.

In order to force AngularJS to skip over encoding the description, we need to inject ng.ISCEService, and call the trustAsHtml method. The method will be called once the description value is known, and for each instance of BreachedAccount in the array.

Directives

Now we need a new AngularJS directive called ngEnter. The purpose of this attribute, which will be attached to a text input field, will be to call a function on our controller when the user presses Enter on their keyboard. This means that the user won’t have to click the left button on their mouse to perform a search, they can do it straight from the keyboard. The beauty of directives is that they can easily be used throughout your application.

The ngEnter attribute will take the name of the method to invoke when the user presses Enter.

Directives are slightly more involved than filters. A typical directive in AngularJS consists of a link function, and a require variable (which determines how the directive is used).

If you want to learn about directives in depth, The nitty-gritty of compile and link functions inside AngularJS directives by Jurgen Van de Moere is a good read.

Start by defining a class, called EnterKeyPressDirective, and implement the ng.IDirective interface;

class EnterKeyPressDirective implements ng.IDirective {
    
}

Doing this doesn’t give us much. In fact, if you take a look at the type declaration file all the functions and properties are optional;

interface IDirective {
    compile?: IDirectiveCompileFn;
    controller?: any;
    controllerAs?: string;
    bindToController?: boolean|Object;
    link?: IDirectiveLinkFn | IDirectivePrePost;
    name?: string;
    priority?: number;
    replace?: boolean;
    require?: any;
    restrict?: string;
    scope?: any;
    template?: any;
    templateUrl?: any;
    terminal?: boolean;
    transclude?: any;
}

However, I’d say it is a pretty good practice to include the interface.

The link function is called after the compile function at runtime. The link function takes 4 parameters and doesn’t return a value;

link($scope: ng.IScope, elm: Element, attr: ng.IAttributes, ngModel: ng.INgModelController): void

The value of ngEnter (the method to invoke) will be passed to us via the attr parameter. The problem is, ng.IAttributes knows nothing about ngEnter.

Create a new interface that extends ng.IAttributes, and add the ngEnter property to it;

export interface IEnterKeyPressAttributes extends ng.IAttributes {
    ngEnter: string;
}

Now replace ng.IAttibutes with IEnterKeyPressAttributes;

link($scope: ng.IScope, elm: Element, attr: IEnterKeyPressAttributes, ngModel: ng.INgModelController): void {
    
}

And flesh out the function as follows;

var element = angular.element(elm);
element.bind("keydown keypress", (event: JQueryEventObject) => {

    if (event.which === 13) {
        $scope.$apply(() => {
            $scope.$eval(attr.ngEnter);
        });

        event.preventDefault();
    }

});

We are using jqLite to subscribe to the elements keydown and keypress events. Once a key is pressed, ensure it is the enter key, and then call the function as defined by the ngEnter variable.

Also, we need to tell AngularJS that this directive requires an instance of ngModel and to restrict the directive so that it can only be used as an attribute. Add the following code to the class;

require = "?ngModel";
restrict = "A";

We finish with a hack. I’m not sure if this is a bug in AngularJS, or expected behaviour.

Each time our directive is required, we need to ensure that a new instance of that directive is created. Add the following static function;

static instance(): ng.IDirective {
    return new EnterKeyPressDirective();
}

For reasons unclear, we have to take care of the leg work of creating a new instance of the directive, because AngularJS doesn’t seem to take care of that for us.

So when defining the directive, pass in the instance function instead of the class. This will then be called each time AngularJS needs an instance of the directive, which will in turn ensure a new instance is created;

angular
    .module("HaveIBeenPwned")
    .directive("ngEnter", EnterKeyPressDirective.instance);

We’re good to go.

Final steps

Add a new file to the root folder called index.html. Also add a CSS file to the css folder, under content, called site.css.

Open index.html and add the following markup;

<html>
    <head>
	<link href='http://fonts.googleapis.com/css?family=Roboto' rel='stylesheet' type='text/css'>
	<link href="content/css/site.css" rel="stylesheet"/>
    </head>
    <body ng-app="HaveIBeenPwned">
	<h1>Have I Been Pwned?</h1>
		
	<div class="container" ng-view>
			
	</div>
		
	<script src="bower_components/angular/angular.js"></script>
	<script src="bower_components/angular-route/angular-route.js"></script>
	<script src="client/HaveIBeenPwned/app.module.js"></script>
	<script src="client/HaveIBeenPwned/app.route.js"></script>
	<script src="client/HaveIBeenPwned/services/pwnedservice.js"></script>
	<script src="client/HaveIBeenPwned/controllers/search.js"></script>
	<script src="client/HaveIBeenPwned/models/breachedaccount.js"></script>		
	<script src="client/HaveIBeenPwned/filters/asHtml.filter.js"></script>	
	<script src="client/HaveIBeenPwned/directives/search.directive.js"></script>	
    </body>
</html>

This will pull in all the relevant scripts, fonts and styles. It will also specify the name of the app (using the ngApp directive) and the view (using the ngView directive).

Open site.css and add the following styles;

body{
    font-family: 'Roboto', sans-serif;
}
h1{
    font-size: 24px;
    text-align: center;
}

.container{
    width:50%;
    margin-left:auto;
    margin-right:auto;
}

input {
    width:100%;
    height:35px;
    font-size: 16px;
    margin:10px auto;
}

button {
    background: #25A6E1;
    background: -moz-linear-gradient(top,#25A6E1 0%,#188BC0 100%);
    background: -webkit-gradient(linear,left top,left bottom,color-stop(0%,#25A6E1),color-stop(100%,#188BC0));
    background: -webkit-linear-gradient(top,#25A6E1 0%,#188BC0 100%);
    background: -o-linear-gradient(top,#25A6E1 0%,#188BC0 100%);
    background: -ms-linear-gradient(top,#25A6E1 0%,#188BC0 100%);
    background: linear-gradient(top,#25A6E1 0%,#188BC0 100%);
    filter: progid: DXImageTransform.Microsoft.gradient( startColorstr='#25A6E1',endColorstr='#188BC0',GradientType=0);
    padding:8px 13px;
    color:#fff;
    font-family:'Helvetica Neue',sans-serif;
    font-size:17px;
    border-radius:4px;
    -moz-border-radius:4px;
    -webkit-border-radius:4px;
    border:1px solid #1A87B9;
    cursor: pointer;
}               

tr:nth-child(even){
    background-color:#eee;
}

tr td {
    padding:10px;
}

It’s going to look functional, not beautiful.

HaveIBeenPwned

 

Enter the test email address, [email protected] and press Enter. You should get some sample data regarding breaches for that account.

Summary

We looked, at a high level, at how to use TypeScript and AngularJS. We looked modules, dependency injection, promises, filters and directives… the most common components of AngularJS 1.x applications. TypeScript’s static typing functionality makes compile time checking and refactoring possible, whilst allowing us to exploit ES6 goodness, resulting in cleaner more maintainable code. We developed a sample application, that made us of the HaveIBeenPwned API to demonstrate these concepts.

Using ES6 features with TypeScript

TypeScript is a transpiler

The TypeScript compiler converts your code from TypeScript, which is a subset of JavaScript, to TypeScript.

Compiler vs. Transpiler

There is some confusion about the difference between a compiler and a transpiler. A compiler takes your code and turns it into something very different, a whole new language.

A good example is with a high level language such as C# or Visual Basic. When you write code and build it, the compiler (either csc.exe [C# compiler] or vbc.exe [Visual Basic compiler] in this case) takes your code and turns it into Intermediate Language (IL).

Example C# code;

private static void Main(string[] args)
{
    Console.WriteLine("Hello, World!");
}

And the compiled code (as seen using ILDasm.exe);

.method private hidebysig static void  Main(string[] args) cil managed
{
  .entrypoint
  // Code size       13 (0xd)
  .maxstack  8
  IL_0000:  nop
  IL_0001:  ldstr      "Hello, World!"
  IL_0006:  call       void [mscorlib]System.Console::WriteLine(string)
  IL_000b:  nop
  IL_000c:  ret
} // end of method Program::Main

The above code is certainly not C#. The C# has been changed into a whole new language.

A transpiler takes your code and changes it. But it’s still in the same language that you started out with. TypeScript is JavaScript, infact, TypeScript is a subset of JavaScript. When the TypeScript compiler runs over your code, it reads in TypeScript (which is JavaScript) and outputs JavaScript. The end resulting language is the same as what you started out with.

The following TypeScript code is completely valid;

(function() {
    console.log("Hello, World!");
});

And the resulting transpiled JavaScript code;

(function() {
    console.log("Hello, World!");
});

Its the same! This is an oversimplification, but the point is correct.

Take the following example, which uses classes (a feature of ECMAScript 6);

"use strict";
class Hello {
    constructor() {
        console.log("Hello, World!");
    }
}
var hello = new Hello();

And the resulting JavaScript transpiled code;

"use strict";
var Hello = (function () {
    function Hello() {
        console.log("Hello, World!");
    }
    return Hello;
})();
var hello = new Hello();

The TypeScript compiler has taken your ECMAScript 6, and converted it to use the IFFE pattern, which is a pattern well supported in all browsers. By the way, the original class based code shown above is perfectly valid ES6 code. You can drop the code into a JS file and load it into your browser and it will work, but ES6 is not as widely supported as ES5 at this time.

TypeScript < 1.5 – Useful ES6 transformations

There are many new features in ECMAScript 6 (ES6) as described in this very good write-up by Luke Hoban on GitHub. I’ve narrowed it down for you to what I think are the most useful and common transformations that you can use right now.

Note: At the time of writing, not all ES6 features can be transpiled. Promises, for example, require browser support and cannot be transpiled to an ES5 equivalent. I don’t expect that trying to fudge in functionality into a browser will ever become a feature of TypeScript, this is something that is best left to a polyfill.

Template strings

Arguably the simplest transformation that TypeScript offers, template strings are simply a way of using variables as part of a string. Template strings use back-ticks “ to denote that a string contains variables.

Usage;

"use strict";
class Hello {
    constructor() {
        var hello = "Hello";
        var world = "World";

        console.log(`${hello}, ${world}!`);
    }
}
var hello = new Hello();

and the transpiled output;

"use strict";
var Hello = (function () {
    function Hello() {
        var hello = "Hello";
        var world = "World";
        console.log("" + hello + ", " + world + "!");
    }
    return Hello;
})();
var hello = new Hello();

At compile time, TypeScript replaces all template strings with simpler string concatenation (which has been around forever!). So you get the niceness of easier to read code without losing the cross browser support.

Personally, I didn’t exactly like this syntax at first, and at the time of writing some JavaScript linters get confused by the lack of spaces around variable names (Web Essentials, I’m looking at you!). But generally this syntax is clean and relatively easy to read.

Classes

We’ve touched on classes several times already at this point, and if you have done any object oriented programming at all there’s no doubt you have already stumbled across classes. Classes are simply containers, they contain information about the functionality the object (an instantiated class) such as methods, members etc. In TypeScript/JavaScript, classes are no different.

Usage;

"use strict";
class Hello {
    public id : number;
    private arbitraryValue: boolean;

    constructor() {
        this.id = 42;
        this.arbitraryValue = true;
        this.sayHello();
        this.saySomething("Goodbye, world!");
    }
    sayHello() : void {
        console.log("Hello, World!");
    }
    saySomething(message: string) :void {
        console.log(message);
    }
}
var hello = new Hello();

and the transpiled output;

"use strict";
var Hello = (function () {
    function Hello() {
        this.id = 42;
        this.arbitraryValue = true;
        this.sayHello();
        this.saySomething("Goodbye, world!");
    }
    Hello.prototype.sayHello = function () {
        console.log("Hello, World!");
    };
    Hello.prototype.saySomething = function (message) {
        console.log(message);
    };
    return Hello;
})();
var hello = new Hello();

You can use the following access modifiers to state the accessibility of your methods and variables;

  • public
  • protected
  • private

Note that these access modifiers are only used at compile time, and don’t affect the transpiled JavaScript.

Arrow functions

Also known as “Fat arrow functions”, because of the use of the equals operator (=>), are inline functions, similar to lambda expressions in C# and Java.

Usage;

"use strict";	
class Hello {
    constructor() {
        var sayHello = () => console.log("Hello, World!");
        var saySomething = (what : string) => console.log(what);

        sayHello();
        saySomething("Goodbye, world!");
    }
}	
var hello = new Hello();

and the transpiled output;

"use strict";
var Hello = (function () {
    function Hello() {
        var sayHello = function () { return console.log("Hello, World!"); };
        var saySomething = function (what) { return console.log(what); };
        sayHello();
        saySomething("Goodbye, world!");
    }
    return Hello;
})();
var hello = new Hello();

Arrow functions in TypeScript allow you to write cleaner, more reusable code without having a bunch of ugly inline functions staring at you.

TypeScript >= 1.5 – Useful ES6 transformations

TypeScript version 1.5 adds support for additional transformations (some of which are shown below). You have to have version 1.5+ installed to take advantage of these features.

“for…of” operator

The concept of a for...of loop is pretty simple. You have an array of objects, and you want to iterate through each item in the array. With a for...of loop you can also break and continue in the same way as you could with a standard for loop. A for...of loop, putting aside small differences in performance when dealing with large arrays (and having to increment a counter to keep the position in the array), is effectively syntactical sugar. And as such, a browser has to have native support for it.

TypeScript, however, transforms a for...of loop to a standard ES5 for loop;

Usage;

"use strict";
class Hello {
    constructor() {
        var a = ['a', 'b', 'c'];
        for (var n of a) {
        	console.log(n);
        }
    }
}
var hello = new Hello();

and the transpiled output;

"use strict";
var Hello = (function () {
    function Hello() {
        var a = ['a', 'b', 'c'];
        for (var _i = 0; _i < a.length; _i++) {
            var n = a[_i];
            console.log(n);
        }
    }
    return Hello;
})();
var hello = new Hello();

let

let in ES6 is a scope version of var. In a nutshell, var is function scoped and let scoped to the enclosing block. There are already lots of good write ups that describe the ins and outs of let vs scope, an especially good one can be found on the Mozilla Developer Network.

The following code, due to the way that closures work in ES5, is valid;

"use strict";
var Hello = (function () {
    function Hello() {
        var array = ['a', 'b', 'c', 'd'];
        for (var index = 0; index < array.length; index++) {
            var element = array[index];
            console.log(element);
        }
        index = 0;
    }
    return Hello;
})();
var hello = new Hello();

The index variable is scoped to the function, not the block. Changing var index to let index results in the index variable only being accessible inside the block.

The following code is invalid;

"use strict";
class Hello {
    constructor() {
	var array = ['a', 'b', 'c', 'd'];
	for (let index = 0; index < array.length; index++) {
		var element = array[index];
		console.log(element);
	}			
	index = 0;
    }
}
var hello = new Hello();

TypeScript allows you to use the let keyword and get all the compile time checking that comes with the feature, whilst maintaining support for older browsers by simply replacing all usages of let with var.

The code shown above transpiles to the following;

"use strict";
var Hello = (function () {
    function Hello() {
        var array = ['a', 'b', 'c', 'd'];
        for (var index = 0; index < array.length; index++) {
            var element = array[index];
            console.log(element);
        }
        index = 0;
    }
    return Hello;
})();
var hello = new Hello();

const

Constants in ES6 are the same concept as in most other programming languages. Traditionally you define a variable using the var keyword. Its value can be read and written at any time. Also, as we’re talking JavaScript (a dynamic language), the type can also be changed at runtime.

For example, the following code is perfectly valid JavaScript;

"use strict";
class Hello {
    constructor() {
	var a = "Hello!";
	console.log(a); //Writes 'Hello!'
	a = 123;
	console.log(a); //Writes 123
    }
}
var hello = new Hello();

A constant in ES6 allows you to set a value and know that value cannot be changed. Take the following code;

"use strict";
class Hello {
    constructor() {
        const a = "Hello!";
	console.log(a); //Writes 'Hello!'
	a = "World!";
	console.log(a);
    }
}
var hello = new Hello();

Running this code results in a runtime error (in Chrome and Firefox, which support the construct);

Uncaught TypeError: Assignment to constant variable.

As const is a native ES6 feature, the ES5 fallback is simply to use a var. This is the transformation TypeScript applies to your code;

"use strict";
var Hello = (function () {
    function Hello() {
        var a = "Hello!";
        console.log(a); //Writes 'Hello!'
        a = "World!";
        console.log(a);
    }
    return Hello;
})();
var hello = new Hello();

Enhanced object literals

More syntactic sugar in the ES6 standard, and this one is especially sweet. Instead of having to define your objects using key value pairs, you can now use a more concise syntax.

Classic ES5 code;

var firstName = "Jon";
var lastName = "Preece";
var person = {
    firstName: firstName,
    lastName: lastName,
    speak: function (what) {
        console.log(firstName + " " + lastName + " said '" + what + "'");
    }
};

You define a couple of variables/functions etc and create an object using keys for property names and values for the value of that property. Functions were also expressed using the function keyword. The enhanced object literal syntax in ES6 allows you to define keys/values in a single pass;

var firstName = "Jon";
var lastName = "Preece";
var person = {
  firstName,
  lastName,
  speak (what) {
    console.log(firstName + " " + lastName + " said '" + what +  "'");
  }
};

And as you might expect, TypeScript transforms this into the long form ES5 format shown above. (Class ES5 code).

Summary

TypeScript is a transpiler, not to be confused with a compiler. A transpiler takes your code and converts it into a similar format, typically the same language you are working in (in this case, JavaScript). A compiler takes your code and converts it into something completely different (think C# to IL for example).

TypeScript allows you to utilize new language features that are appearing in newer revisions of the ECMAScript standard (6 at the time of writing) and have them transpiled into a form that is widely supported across browsers (ES5 in this case).

Today you can take full advantage of Template String, Classes, Arrow functions, the ‘for…of’ loop, let + const, enhanced object literals, and more without having to worry if they will work in legacy browsers.

Getting started with TypeScript

This is the 101 tutorial which describes getting started with TypeScript using either the TypeScript Playground, Node.js or VS Code.

At its simplest, TypeScript is a programming language that provides optional static typing for JavaScript.  TypeScript is JavaScript.  Any valid JavaScript is valid TypeScript.  The beauty of TypeScript is that you can define types for your JavaScript variables and functions, and get compile time error checking and error reporting.  This tutorial focuses on getting started with TypeScript and demostrates the basics to get up and running quickly.

TypeScript Playground

The quickest, easiest way to get started with using TypeScript is to experiment with the TypeScript playground.  The TypeScript playground enables you to write TypeScript code in the browser, and see the resulting compiled JavaScript alongside.

First things first, TypeScript doesn’t try to force you to write code in a particular style.  In fact, you can write 100% pure JavaScript code in get the same code out at the other end.

Try entering the following code in the TypeScript pane on the left;

(function(){
	console.log("Hello, world!");	
})()

See the output?  Identical.  You can take advantage of TypeScript is much or as little as you please.

Refactor the code a little bit, introducing a log function as follows;

(function () {

	function log(message: string) {
		console.log(message);
	}

	log("Hello, World!");

})();

Click the “Run” button on the top-right hand side and press F12 to bring up the developer tools in your browser. Click on the “Console” tab and you should see the message “Hello, World!”.

Hello World!

What happened? Well, not a lot (or so you might think!).  Take a look at the compiled JavaScript code;

(function () {
    function log(message) {
        console.log(message);
    }
    log("Hello, World!");
})();

JavaScript is a dynamic language, it has no concept of types (that’s what TypeScript provides!).  TypeScript uses the type information to catch coding errors at compile time and provide other IDE functionality.  TypeScript generates 100% vanilla JavaScript code that is fully cross browser/cross operating system compatible.  By default, TypeScript will generate ECMAScript 5 (ES5) compliant code, although at the time of writing it is possible to generate ES3 and ES6 code too (and no doubt support will be added for ESx on a yearly basis).

Change the code as follows (changing the log message from a string to a number);

TypeScript Compile Time Behaviour

Three very interesting things have happened here, and this is the perfect demonstration of the general attitude of TypeScript.

Looking at the red arrows, in order from left to right

  1. You get compile time checking.  TypeScript recognizes that you have supplied a value to the log method that is not a string, and highlights the erroneous code to you.
  2. You get a detailed error message that explains in simple terms what the error was, and the type of value that the calling method was expecting (this is typical behaviour regardless of the complexity of code you are writing).
  3. The JavaScript code is generated regardless of these compile time errors.  TypeScript does not force you to adhere to its paradigm.

 

Node.js

You might be surprised to see Node mentioned on this page.  TypeScript is a Microsoft product right? Traditionally tools like this might have been constrained to Microsoft IDE’s or operating systems, but today’s modern Microsoft is moving away from that traditional stance and moving towards being more open.

TypeScript is not only completely free, open source, cross browser, cross operating system, but it is also community driven and actively accepts pull requests directly from community members.  In fact, the tooling is so good that its becoming widely adopted in many IDE’s including (but not limited to);

If you already have Node and Node Package Manager (npm) installed, open a Node.js command prompt and enter the following command to globally install TypeScript;

npm install -g typescript

This will install the TypeScript compiler onto your machine and into your PATH environment variable so you can call it directly.  Change directory to your desktop, and create a file called helloworld.ts.  Add the following code;

(function () {

	function log(message: string) {
		console.log(message);
	}

	log("Hello, World!");

})();

Now enter the following command;

tsc -w helloworld.ts

The watch flag (denoted by the -w) tells the TypeScript compiler to watch your file.  Meaning that, if you make some edits and save your changes, TypeScript will automatically recompile the file for you each time.

Open the helloworld.ts file in Notepad, make a small change, save the file.  You should notice the JS gets updated automatically.

TypeScript compilation completed

 

VS Code

VS Code, at the time of writing at least (they may or may not streamline this process in the future), requires a little more leg work to get TS files to compile (almost) automatically.  You can find a more comprehensive tutorial over on MSDN, but this is how you get up and running quickly;

  • Create a new folder on your desktop and create a new file called helloworld.ts (or use the one you created for the Node.js part of this tutorial).
  • Add the code shown above, named Log function with string type definition.
  • Open VS Code, click File > Open Folder… and point to the new folder you just created.
  • Add a new file called tsconfig.json, and add the following;
{
    "compilerOptions": {
    "target": "ES5"
    }
}

Press Ctrl+Shift+B on your keyboard.  This would normally kick off the task runner built into VS code.  However, we haven’t configured the task runner yet, so a small toolbar will appear at the top telling us there is no task runner configured.  There is a handy button on the right that says “Configure Task Runner”.  Click the button.

Configure VS Code Task Runner

VS Code will now generate a bunch of TypeScript specific configuration for us.  This will be covered in detail in a future post.  For now, however, just accept that TypeScript is ready to go.

Switch back to your helloworld.ts file, click Save and open the equivalent JavaScript file (helloworld.js).  You  should see the compiled output.  It can be helpful to put the two files side by side you that you can see the updated changes every time you click Save.

Side By Side View

Wait, there’s more!  TypeScript is a transpiler too…

A transpiler is a method of converting code from one language to another.  So what does this mean for us?

TypeScript allows us to utilize more modern language constructs, which will be transpiled into a more widely supported form.  The simplest example is string interpolation (also known as template strings), which is a feature of the ECMAScript 6 (ES6) standard.

Take the following ES6 code (1 – String Interpolation – template strings);

(function () {

	var hello = "Hello";
	var world = "World";
	
	var message = `${hello}, ${world}!`;

	console.log(message);

})();
(function () {
    var hello = "Hello";
    var world = "World";
    var message = hello + ", " + world + "!";
    console.log(message);
})();

Template strings are not supported in ES5, they are an ES6 feature only.  TypeScript knows this and automatically converts the code into a ES5 compliant form, the process of which is called Transpiling.  We will discuss this in more depth in future posts.

Summary

TypeScript is a free, open source, cross-browser, multi-OS tool from Microsoft that enables (but doesn’t force) static static typing.  TypeScript generates 100% vanilla JavaScript code that is fully cross browser/cross operating system compatible.  Tooling exists for a wide variety of editors/IDE’s include Node, Visual Studio, VS Code, Sublime Text and many more.  As an additional bonus, TypeScript is also a transpiler, meaning you can write code using modern ECMAScript 6 constructs and the resulting code will be ECMAScript 5 compliant.

TypeScript Tips and Tricks

Automatically compile TypeScript files when using VS Code

If you’re writing TypeScript using Visual Studio, your files are automatically compiled when you save (assuming you haven’t turned this off…the feature is found in the Project Properties > TypeScript Build screen).

If you don’t use Visual Studio, and instead are using a lightweight IDE such as VS Code or Sublime Text, you don’t get this feature.

Manual compilation

First things first, how would you normally compile a TypeScript file to JavaScript? VS Code doesn’t do this out of the box (perhaps the will add this functionality in the future, I’m not sure). You use a task runner.

To configure a task runner, open your project that has some TypeScript files, and press Ctrl+Shift+B. A little notification to appear that tells you that no task runner is configured. Click Configure Task Runner. VS Code will create a directory called .settings and add a new JSON file called tasks.json to this directory.

Open tasks.json and inspect the default configuration (the one that isn’t commented out, VS Code will show you some other sample configurations that are commented out. Look for the following line;

"args": ["HelloWorld.ts"]

Change this path to point at a TypeScript file in your project. Save changes.

Now open your TypeScript file, and open in it in side by side view. Put the TypeScript file (.ts) on the left, and put the compiled JavaScript code (.js) on the right.

Make a change your TypeScript file and press Ctrl+Shift+B again. You should see the updated JavaScript file.

Automatic compilation

Having to press Ctrl+Shift+B every time you want to compile your TypeScript files gets really old, really fast. Lets say to make a change, you refresh your browser and the change hasn’t been applied. You open the dev tools, start debugging, and hang on…where is your code? Oh right yeah, you forgot to run the task runner. Rinse and repeat.

Instead of using a task runner to call the TypeScript compiler (tsc.exe), we can instead make tsc work for us, using the -w flag, called the watch flag.

Wrong Way

My first thoughts when trying to get this to work were to pass the -w flag to tsc using VS Code. Try opening tasks.json and changing the args option as follows;

"args": ["-w", "test.ts"],

Yeah that doesn’t work (even though other sample configurations shown in the same file pass commands to tsc in this manner).

Right Way

The best way to do this is via the command line. Open a Node.js command prompt window, and change directory (cd) to your project folder. Now run the following command;

tsc -w

This will listen for changes in the given directory, and all sub directories. Whenever a change is made, the file will be recompiled automatically. So now, pressing Ctrl+S on the keyboard will cause the file to be recompiled.

We’re almost there. If you want the file to automatically compile pretty much as you type (not quite that frequently, but almost as good), you can enable Auto Save in VS Code. Click File > Auto Save to turn it on.

Success! All your TypeScript files will be automatically saved and compiled as your work on them, with no keyboard presses needed.

I mentioned Sublime text at the beginning of this tip, because of course this isn’t a VS Code specific feature. You can easily enable this regardless of the editor you are using.

Source maps

Source maps are are means of rebuilding compiled and minified code back to its original state. When you write TypeScript, it is transpiled to JavaScript and can be minified to reduce bandwidth costs and improve page load times. This process, however, makes debugging virtually impossible due to the fact that all variable names are changed, all white-space and comments are removed etc.

Browsers use source maps to translate this code back into its original state, enabling you to debug TypeScript code straight from the dev tools. Pretty neat huh?!

Modern browsers (IE10, Chrome, Firefox) enable source maps by default.

However, I have on many occasions encountered errors and inconsistencies when using source maps, and it is not just me who is encountering these issues. The dev tools might tell me, for example, the wrong value for this. TypeScript captures the value of this in a local variable, so that, in theory, you’re always using the right this (it typically captures the instance of the class itself). Often, however, dev tools will incorrectly tell me that this is an instance of window… rendering the debugger useless.

How to turn source maps off

There are a couple of ways to approach this.

Stop generating source maps

TypeScript is generating the source maps for you.

If you are using Visual Studio, you can stop generating source maps by going to Project Properties > TypeScript Build and un-checking Generate Source Maps. Be sure to rebuild your project.

For everybody else, you simply don’t pass in the –sourcemap argument to tsc.

Disable source maps in the browser

Modern browsers have the ability to disable source maps.

Chrome
1. Open dev tools
2. Settings
3. Sources (middle column)
4. Enable JavaScript source maps

Firefox
1. Open dev tools
2. Debugger
3. Settings
4. Un-tick “Show Original Sources”

Combine output in a single file

There are a bunch of tools available to take care of bundling and minification of JavaScript files. You’ve probably used either ASP .NET Bundling & Minification, Web Essentials bundler, Uglify or something similar. These tools generally work well and I’ve only experienced minor problems with each tool. (The ASP .NET bundler is a bit more troublesome than most, to be fair).

When using a task runner such as Grunt or Gulp, you pass in an array of all the file paths you want to include in the bundle.

Example;

files: {
        'dest/output.min.js': ['src/input.js']
      }

Generally I don’t take this approach of passing in individual files, I prefer to pass in a recursive path, perhaps something like this;

"**/*.ts"

That aside, if you prefer to include your files individually in Grunt/GulpFile, TypeScript can help you out by combining all the compiled JavaScript into a single file.

Using Visual Studio

If you’re using Visual Studio, there is a simple user interface to set this up. Right click your project and select Project Properties > TypeScript Build.

Under the Output header, there are two options of interest;

  1. Combine JavaScript output into file: – Name of the file to put the merged JavaScript.
  2. Redirect JavaScript output to directory: – The folder in which to put the merged file.

Typically you would use these two in conjunction with each other. You can then modify your Grunt/GulpFile to point at the merged file, rather than all your un-merged JavaScript files.

Via command prompt

The flags you need are as follows;

--out FILENAME
--outDir DIRECTORYPATH

Available from version 1.5

Version 1.5 of the TypeScript compiler (version 1.5.3 to be precise, use the -v flag to check you aren’t using 1.5.0 beta) adds a few additional features of some use (this is not an exhaustive list);

-m KIND or –module KIND

Ok this isn’t new, but TypeScript 1.5 has added support for UMD and System, so you can now pass the name through to use that module system. There is an updated UI in Visual Studio 2015 RTM for this feature.

–noEmitOnError

Doesn’t generate any JS files if any compile time errors are detected. You might want to turn this off if you want to ignore certain errors (like, incorrect or incomplete type declaration file).

–preserveConstEnums

The default behaviour in past versions of tsc was to remove enumerations and replace them with te actual value of the enumeration.

So if your enum was;

enum DaysOfWeek{
    Monday,
    Tuesday
    ... 
}

...

console.log(DayOfWeek.Monday)

The transpiled output would be;

console.log(0 /*Monday*/)

Passing the –preserveConstEnums flag prevents this transformation from taking place, so the original code stays in act.

Summary

The TypeScript compiler is flexible and configurable and has a wealth of flags that can be passed to it to change the transpiled output. Using Node.js tools, you can easily have your TS files automatically transpiled, you can have source maps for a better debugging experience, and you can have all the transpiled TS files merged into a single file for easier uglification.

I’ll update this post with new tips and tricks as I come across them. If you ave any good ones, let me know in the comments or get me on Twitter, and I’ll update the post accordingly.

If you’re interested in learning about all the different compiler flags that TypeScript accepts, you can find them in GitHub.

What I learnt from using TypeScript “for real”

I completed my first commercial Greenfield project using TypeScript over plain old JavaScript throughout, and there were some frustrations along the way.

 

TL;DR

  • TypeScript is awesome, for sure, but there needs to be improvements to tooling to streamline the experience.
  • TypeScript is strongly typed of course, but it doesn’t force you to code in this manner, which can result in shoddy code.
  • Tweaking is required to make bundling work properly.

 

Tooling Frustrations

When I started the project, I was using Visual Studio 2012 Update 4 with TypeScript 1.0 pre-installed.  I was brought in to work on this project on a short term basis, and this is how the machine was set up when I arrived.  Normally I wouldn’t choose to use Visual Studio 2012 (I like to use the latest tools where possible) but I decided to just go with it and make do.  Once deficiencies in tooling became clear, I did eventually push for an update to Visual Studio 2013 Update 4, which in fairness resolved most of my frustrations.

I have a license for JetBrains ReSharper, which has support for TypeScript 1.4 (and indeed that is the default setting when using ReSharper 9).  This was actually my first tooling problem.

When using Visual Studio 2012, you are using TypeScript 1.0 (unless you have proactively updated to version 1.4).  Naturally 1.0 is an older version and doesn’t support language features such as protected methods or ECMAScript 6 template strings.  ReSharper, however, does understand these features and offers suggestions to use them.  Trying to use these features results in build errors, which of course was confusing because I didn’t understand that I was actually using version 1.0 at the time (does it say anywhere? not to my knowledge).

Also, due to the aforementioned old version of TypeScript, I also encountered an issue with TypeScript definition files.  These files are designed to not only provide IntelliSense in Visual Studio when working with third party libraries such as AngularJS, but also are used during the build process for compile time checking.  Because the TypeScript definition files (sourced using NuGet via GitHub) were based on TypeScript 1.4, again hundreds of errors at compile time.  Interestingly, however, with version 1.0 it was actually possible to ignore these build errors and still generate the compiled JavaScript files.  Only once upgrading to version 1.4 later on did it become mandatory to fix these build issues.

Compile on save does what it says on the tin.  You write some TypeScript code, click Save, and the JavaScript file is generated automatically.  Well, actually, no.  There were dozens of occasions when this just didn’t work.  I had to literally open the scripts folder, delete the JavaScript files manually, re-open Visual Studio, and save the TypeScript file again before it would actually recompile the JavaScript file.  This was tedious and boring and didn’t seem to be resolved by upgrading to Visual Studio 2013 Update 4 (although it did become less frequent).  I have Web Essentials installed, which gives you a side by side view of the TypeScript and JavaScript files which I originally turned off.  I did eventually turn this back on so I could see if the files were being recompiled at a glace before refreshing the web browser.

On a side note, the tooling provided by Google Chrome developer tools is excellent.  You can debug the actual TypeScript source directly in the browser, and if you inadvertently set a breakpoint on a JavaScript file, Chrome will navigate you back to the TypeScript file.  Nice.

 

Bundling in MVC

The project I was working on used some features of ASP .NET and Web API.  One such feature was bundling and minification, which I always use to improve performance and reduce server load.  I wrote many based files and interfaces as you would expect, as both are fully supported in TypeScript.  However, what I later realised (perhaps I should have realised at the start, but hey) was that order is important.  The MVC bundler doesn’t care about order, so there’s a big problem here.  After switching on bundling, I went from 0 runtime errors to at least 20.  There are two approaches I could have taken to resolve the problem;

  1. Create two separate bundles, one for base classes, the other for derived classes (I don’t care for this)
  2. Create a custom orderer and use naming conventions (prefix base class files with the name “Base”) to ensure order.

I went for the latter option.  This involved having to rename all my base class files and interfaces (granted interfaces don’t actually generate any JavaScript, but I wanted to keep the naming consistent) and writing a custom convention based orderer.  Neither of these things were challenging, just time consuming.

 

TypeScript is inconsistent

I can only speak from my own experiences here.  I don’t claim to be a TypeScript or JavaScript master, I’m just a normal developer as experienced as anybody else.

I love the strongly typed nature of TypeScript, that’s the feature that appeals most to me.  I do however have the following qualms;

 

TypeScript does not force you to use the language features of TypeScript

This is either a good thing, or a bad thing.  I can’t decide.  To be honest, I wish TypeScript did force you to use its own paradigm.  You can easily write pure JavaScript inside a TypeScript file and it will all compile and “just work”.  This is a bit of a downfall for me because I’ve always found JavaScript to be frustrating at best (can you think of an application you’ve written in JavaScript that hasn’t eventually descended into mayhem?).

What I mean is this, I can create a local variable and assign it a type of Element;

var element : Element = angular.element('.myelement')

The type constraint is redundant, and ReSharper makes a song and dance about the fact and basically forces you to get rid of it (yeah, I know I could turn this off but at the end of the day ReSharper is right).  I can assign function parameters type declarations, but I don’t have to.  (I did eventually go back in fill these in where I could).  I know that I should use type declarations and to be honest I wish I did use this feature more, but I’m lazy.  Next time I’ll be sure to do this from the start as I think it adds further structure to the code.

 

TypeScript doesn’t know it all

The project I was developing was built in conjunction with AngularJS.  I’ve had an up-down relationship with AngularJS to say the least, but I decided to fully embrace it this time and not switch between jQuery and Angular (yeah I’m aware that Angular uses jQuery lite under the hood, I’m referring to not switching between using $() and angular.element()).  I made heavy use of Angular Scope and I often had a dozen or more child scopes running on any one page.  So as a result, I had lots of code that looked roughly like this;

var scope = angular.element('.myselector').first().children('.mychildren').scope()

That’s perfectly valid code.  Even though I have already added the appropriate type definition files and referenced appropriate at the top of the file, TypeScript still insists that scope() is not valid in this context and I get a compilation error.  So I’d have to exploit the dynamic functionality of JavaScript to get around this;

var children = angular.element('.myselector').first().children('.mychildren');
var scope = children.scope();

Ok its not a big deal.  The scope variable is now of type any, so there’s no IntelliSense and no compile time checking.  But hey, wait, isn’t that the main point of using TypeScript in the first place?  Now if I pass scope to another function, I’ll exacerbate the problem (due to the fact that the parameter will have to be of type any) and before you know it, I’m just writing JavaScript again.  Fail.

Positive note

I’ve ranted about what I don’t like about TypeScript, and the frustrations I’ve encountered so far, but honestly I can’t sign its praises enough.  I estimate that so far TypeScript has saved me at least 3 million hours of effort.  Ok, perhaps a slight exaggeration, but you get the point.  Writing TypeScript is easy and familiar because I am comfortable with JavaScript and strongly typed languages such as C#.  I did spend perhaps a few hours reading the documentation and experimenting in the excellent TypeScript playground (both of which are excellent by the way), but generally thanks to previous experience with the aforementioned languages, I found that I “just know” TypeScript and it has a very smooth learning curve.

 

Summary

TypeScript is awesome, there is no doubt in my mind about that.  TypeScript saves all the pain that naturally comes with JavaScript and its only going to get better over time.   The tooling issues and inconsistencies are relatively insignificant, once you get used to them.