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.

Devs, this is how I got fit

Right now, I’m in pretty good shape. I have the confidence to say this because I’ve worked very hard over the last 18 months to get to this point. I’m not a muscular person, like what you might see in a designer underwear advert…and this was never my personal goal, but I certainly don’t feel embarrassed anymore when I take my shirt off. I’ve discovered a few very simple patterns for losing weight, gaining muscle (at a slow rate) and generally feeling better about myself. This has been such a big success for me, that I felt it only right to share with you.

I talk about myself a lot in this post, and I apologize for that, but it’s hard not to. I believe that if you follow this advice and these tips, you can achieve the same results as me.

Backstory

Poor diet, smoker, drinker, allergic to exercise guy

Growing up as a teenager in North-West England, UK, in the early 2000’s, I was skinny. I had an extremely poor diet and frankly was “allergic” (not literally, just mentally) to vegetables and healthy food in general. I flat out refused to eat vegetables because I simply didn’t like them. For tea I would have “chips and something”, usually chicken, beef, pork, typically skins on and deep fried.

My diet only got worse as I got older. I worked for a fast food chain for a while, and would regularly eat 3 meals on site up to 5 days a week (this particular fast food restaurant classifies you as a “heavy user” if you consume their food once a week).

When I became independent, i.e. I moved out of my parents house and got my own place, the trend continued for years.

As a software developer, a crazy obsessive one at that, I would spend all my time programming or playing on the games console (PS2/3, or XBox 360). Going outside wasn’t something I would do in a typical month. For a long time, I worked from home and would rarely venture outdoors. Basically I was very inactive, other than to empty the bin or to pick up the post (thank goodness for the elevator in our apartment block!).

At the time, I also smoked and drank alcohol heavily. My favourite tobacco was Golden Virginia (or Amber Leaf if money was a bit tight) and I was an avid whiskey drinker. Every Saturday night I would get so drunk that I would often end up being sick and doing much worse things than I care to share with you!

Any of this sound familiar?

The eureka moment

I think I’m relatively unique in that I didn’t have a eureka moment as such. Over a period of a few months I came to dislike my appearance. I would look at myself in the mirror, typically after a shower or when getting dressed, and I didn’t like what I saw. I wanted to do something about it, but I never made a serious commitment to actually do anything.

I had a couple of fads. I bought myself a press-up bar. Basically it was a small piece of equipment that helped you do push ups, and also doubled up as a pull-up bar that could easily be attached to a door, with no screws required. I would have a go a couple of times a week…hell I might even do 1 or 2 push-ups and a couple of pull-ups. But to be honest, I never once even broke a sweat.

For the last few years, I’ve been waking up early in the morning at the weekend. This is because my body behaves the opposite to most people. When I drink a lot of alcohol, my body temperature increases dramatically and as a result I can’t sleep. I get too hot for sleep, so I go downstairs and do something useful. I might write a blog post, watch a PluralSight course, write some code, or do something. As its typically around 3-4am, the place is very quite and I typically get a lot done, which is great, so this works well for me.

One day, I switched on the TV and one of those sucky TV shopping channels was on. I immediately reached for the remote control, but in the 2.5 seconds it took me to grab the it, I was instantly captivated on what they were advertising.

Insanity

Insanity is an exercise program for regular people, thin people, fat people, tall people, short people, men, women, fit people, people looking to lose weight or gain muscle or all of the above. This was a training programme for me that would get me on the road to good health and fitness. Insanity is a 9 week (60 day) workout program that requires no equipment, and can be done at home.

You work out 6 days a week, for a varying amount of time between 38 minutes and 60 minutes. The first week hurts like hell. After that, you get used to it but it never gets easier. In fact, the harder you push yourself, the more rewarding it becomes. Insanity is great for toning your body, improving your general health and fitness, and it gets you active.

The best part of Insanity? Its all you. No gym, no equipment, no public shame, no awkward showers. You do the workout in the comfort of your own home, and at a time that suits you.

Educating myself about food

Insanity had captured my interest and I instantly knew that I wanted to do it. Over the years I have gone from being the sort of person who makes snap decisions, takes risks, and generally doesn’t engage the brain before speaking, to a deep methodical thinker less inclined to take risks, but whom favours calculated risks.

If this was going to work, I had to give it 100% commitment. No excuses, no BS, no slip ups..for 9 solid weeks. I immediately set about educating myself about food.

Calorie Requirements

I had heard the term, like most people, “calories”. I knew that food contained calories. Healthier food contains less calories and unhealthy food contains more calories. Strictly speaking, this is not always true, but that is the basic idea. My body is a power station, and calories are its fuel. Understanding how many calories my body needs was the first challenge.

In the food guide that accompanied the Insanity workout programme was a useful formula for calculating your bodies calorie needs. The formula was based on the Harris Benedict equations. I typed up the formula into Microsoft Excel and added about 30%, as recommended by the guide based on the frequency of exercising I was planning on doing.

Using this very simple formula, I determined that I needed to consume about 3000 calories a day to lose weight and survive the workouts. To put that into perspective, the average male requires around 2500 calories a day to maintain their body-weight, and I would have to eat more than that!

I had already learnt my first lesson. It is possible to eat more food and still lose weight, as long as the food was fresh and healthy.. The first step was to throw away all the junk food in every cupboard in my kitchen. And that included sugar, soft drinks, and all the processed frozen food in my freezer.

Eating healthily

After determining how many calories my body needs to function correctly, and withstand regular exercise, I now had to understand what foods contained what calories. If I was going to consume 3000 calories a day, which is not a small task, I would need a solid plan and schedule for eating, cooking, and cleaning (cooking generates a lot of dishes!).

The key to losing weight is to eat more food. As many as 5 meals a day. This may seem like bad advice. After all, if you want to lose weight, then you should surely eat less food, right? Well no. The idea is that the more food you eat, the more energy your body uses to digest and process said food. If you eat 5 times a day (breakfast, morning snack, lunch, afternoon snack, evening dinner) then your body is going to be continuously processing food, and burning calories in the process. If you’re eating good, healthy, nutritional food which is low in fat and high in protein (and moderate in carbohydrates), combined with very regular, high intensity training, then you end up in caloric deficit (you have less calories left over than your body needs to maintain weight, therefore you lose weight).

How do you eat healthily?

Pro tip 1 – Plan all meals in advance

Before you deep dive into buying every fruit and vegetable on sale at the supermarket, you should take a step back and plan what you’re doing to eat. This is an alien concept to a lot of people today, but you can actually think ahead of time, list all the ingredients that make up each of your meals, and buy all those ingredients in a single trip to the supermarket each week. Only going shopping once a week is not only going to save you money (no impulse buying) but it will save you time (handy, because you’re going to need that for exercising) and reduce temptation/chances of falling off the wagon.

Sit down and research all your meals, list all the ingredients on a Microsoft Word document, and gather together all the recipes you need.

Here are 3 different shopping lists I have put together that you can use as an example. Note that these lists are catered to my personal needs and tastes, and you may need to adjust accordingly. They’re also not 100% accurate.

  • Current shopping list. This is the list I’m using right now (I’m doing daily fasting at the minute, which is why there are no breakfasts or snacks)
  • Insanity shopping list. Based on the Insanity healthy eating plan, with several customizations for my own tastes.
  • Focus T25 shopping list. Based on the Focus T25 healthy eating plan, again with my own twists and customizations.

As a very important note, you need some self discipline here. Whatever eating plan you use, you should stick to it 100% with no slip ups, snacks, nipples, nothing. Losing weight is a serious commitment and can easily be derailed by the odd treat.

On the other hand, I regularly schedule a treat meal for myself (perhaps once a week). This might be on a Friday night as a reward for the hard work done during the week, but it is always planned ahead of time and is never done on impulse.

Avoid all trans-fats (bad fats), cut all sugar out of your diet, excluding that found in fruit, and eat protein rich foods such as; chicken, beef and turkey. Nuts are super healthy and contain a lot of good fats that your body needs. My favourites include; walnuts, pecans, hazelnuts, cashews and some dried fruits with a twist of salt.

Note, I recommend changing up your meal plan every 4 weeks. There are two reasons for this. First is that eating the same food over and over gets boring. Second is that your body certainly seems to get used to the food your body consumes, and your weight loss my plateau or stop altogether. Shaking things up stops this from happening. You will also want to revisit the Harris Benedict equation from time to time to make sure you are consuming the correct amount of calories (this figure will likely decrease as your body weight decreases).

Pro tip 2 – Always cook fresh

I mentioned earlier that you will save a lot of time not going to the supermarket every day, because you’ve bought all your fresh food in a single trip to the supermarket each week.

I highly recommend that you cook all your meals fresh and just-in-time. This can be time consuming, but here are some tips to make it work;

  • Cook several meals at once. If you can, cook breakfast, lunch and dinner at the same time. I typically do this when cooking the dinner each evening. Stick breakfast and lunch in the fridge, and tuck in to dinner straight away.
  • Recruit a significant other to chip in with the dishes. Ask your other half, girlfriend, wife, (mother?), to give you a hand with the dishes. Have one person washing and one person drying. This will speed up the task dramatically.
  • Memorize each dish. You’ll get the cooking done much quicker if you know the timings, quantities and everything else without having to look at your chart/recipe list. However, be sure to have it on hand if needed.

Pro tip 3 – Eat or starve

If you are like how I used to be, i.e. “allergic” to any form of even remotely healthy food, you should use the Eat or starve technique. It’s pretty simple really, eat the food you have prepared, or go without. Don’t buy any “extras” from the supermarkets, and throw away or donate any unhealthy food you have lying around to somebody who needs it. After a couple of days, once your stomach is rumbling continuously, your taste buds will dull slightly and you’ll become more open to experimentation. Treating yourself when nobody is looking is going to do a lot more harm than good.

Another good tip, and I have done this myself several times, If you find it particularly difficult to eat a particular type of food (a salad for example) then go to a very public place and eat it there. Get together with a group of friends and order something healthy. You’re not going to embarrass yourself in front of your peers by not eating it, especially if everybody else is eating healthy too!

It’s also a good idea to take daily vitamin supplements, to be sure that your getting all the vitamins and minerals your body needs.

Exercising regularly

I’ve learnt a little secret that people generally don’t seem to know about. You don’t have to exercise to lose weight. In fact, if you are quite a bit overweight, I would recommend that you actually do no exercise at all for the first 2-3 weeks of your diet (or longer, if you’re quite a quite a bit overweight [not a typo!]). You’ll shed the pounds quickly to start off with, weather you exercise or not.

What is the purpose of exercising? Exercising is great for toning your body, building muscle, improving your core strength and generally helping you feel happier within your own skin. Exercise gives your body definition and shape.

Workout at home to start off with

Signing up for the gym is a huge commitment. Not only is it potentially expensive (the average gym membership fee is probably between £20-£50 a month), but it requires a lot of your time.

If you go to the gym, you have to;

  • Drive or walk to the gym
  • Say “Hi!” to the receptionist
  • Negotiate several layers of security, using various levels of security cards or keys
  • Find a safe corner in the locker room where you feel comfortable enough to change
  • Pluck up the courage to work out in front of other people, and occasionally have to speak to people (!) when you cross their paths
  • Negotiate the showers and the soap
  • Get dressed
  • Drive home, and sob about the whole experience.

As a beginner, this indeed can be a very trying and stressful process. And ideally, you would repeat this 3-4 or perhaps 5 times a week depending on your programme.

There is an alternative, my friend, workout at home;

  • Drive home (you were going there anyway)
  • Get changed in comfort of your own house
  • Work out in total privacy
  • Get showered, and dressed in private.
  • You’re already home! Time to relax.

There are many home based workout programmes out there. My favourite’s are Insanity: The Ultimate Cardio Workout and Fitness DVD Programme and Shaun T’s FOCUS T25 DVD Workout Programme, both are very popular. If you don’t like the look at either of these programmes, have a browse around the web and find something similar that will work for you. Start with Amazon, I’m sure there are hundreds!

Measure, measure, measure.

If you are going to embark upon an exercise and workout programme, I highly recommend that you set realistic targets, and track your progress every single day.

So as a ritual, when you wake up in the morning, do the following;

  • Go to the toilet, do all your business.
  • Weigh yourself, write it down.
  • Measure your chest, arms, belly, and thighs. Write it down.

This might seem obsessive at first, and perhaps it is a little, but measure your performance on a daily basis will help you maintain your focus (and actually becomes a little exciting after a while!).

Protein supplements

To finish the story

At the peak, I was approaching 14st (196lb). As somebody who is of a slender frame, this was very scary to me and according to my BMI, I was well in the “Overweight” category.

Today, I am a very healthy 11st (154lb) and I feel great. I am still eating healthily and I am doing the intermittent fasting eating regime, as discussed by James Clear on his blog. I exercise every single day, and hit the gym regularly. I now have good respect for food and I enjoy eating and preparing it. Turning my life around has made me a happier person and a better, more focused developer. You can achieve the same too. The trick is, it starts today.