Mastering TypeScript

4 (1 reviews total)
By Nathan Rozentals
  • Instant online access to over 8,000+ books and videos
  • Constantly updated with 100+ new titles each month
  • Breadth and depth in over 1,000+ technologies
  1. TypeScript – Tools and Framework Options

About this book

The TypeScript compiler and language has brought JavaScript development up to the enterprise level, yet still maintains backward compatibility with existing JavaScript browsers and libraries.

Packed with practical code samples, this book brings the benefits of strongly typed, object-oriented programming and design principles into the JavaScript development space. Starting with core language features, and working through more advanced topics such as generics and modules, you will learn how to gain maximum benefit from your JavaScript development with TypeScript. With a strong focus on test-driven development and coverage of many popular JavaScript frameworks, you can fast-track your TypeScript knowledge to a professional level. By the end of this book, you will be able to confidently implement a TypeScript application from scratch.

Publication date:
April 2015
Publisher
Packt
Pages
364
ISBN
9781784399665

 

Chapter 1. TypeScript – Tools and Framework Options

JavaScript is a truly ubiquitous language. Just about every website that you visit in the modern world will have some sort of JavaScript component embedded in it, in order to make the site more responsive, more readable, or more attractive to use. Think about the most impressive website that you have visited over the past few months. Was it visually appealing? Did it have some sort of clever presentation? Did it engage you as a user, by giving you a completely new way of discovering car-insurance, or image-sharing, or news articles?

This is the power of JavaScript. JavaScript is the icing on the cake of the internet experience, that makes millions of people around the world go "wow. That's cool". And it generates revenue. Two websites may offer the same product, at the same price, but the one that engages the client – and makes them enjoy the web experience – is the site that will attract the most followers and be the most successful. If this website can also be seamlessly reproduced on desktops, mobiles or tablets, then the target audience – and the target revenue – can be increased exponentially.

On the flip-side, though, JavaScript is also responsible for the annoying side of the Internet. Those annoying advertisements, where you have to wait for 5 seconds before clicking on the skip button. Or websites that do not quite work on older browsers, or don't render correctly on tablets and mobile phones. It can be argued that many websites would be better off without JavaScript.

An engaging web experience can also make the difference in corporate web applications. A clunky, difficult to use, and slow web application will turn otherwise keen corporate users completely against your application. Remember that your typical corporate user is comparing their work experience to their daily web experience – of well designed, responsive, intuitive interfaces. After all, they are generally users of the most popular websites out there, and come to expect the same responsiveness at work.

Most of this enhanced user experience comes from the effective use of JavaScript. Asynchronous JavaScript requests allow your web page to render content to the user faster – while waiting for backend processes to do the heavy, time consuming data crunching tasks.

The JavaScript language is not a difficult language to learn, but it does present challenges when writing large, complex programs. Being an interpreted language, JavaScript has no compilation step, and so is executed on the fly. For programmers that are used to writing code in a more formal environment – using compilers, strong typing and well established programming patterns – JavaScript can be a completely foreign environment.

TypeScript bridges this gap. It is a strongly typed, object-oriented, compiled language that allows you as a programmer, to re-use the concepts and ideas of well-established object-oriented languages – in JavaScript. The TypeScript compiler generates JavaScript that adheres to these strongly typed, object-oriented principles – but at the same time is just pure JavaScript. As such, it will run successfully wherever JavaScript can run – in the browser, on the server, or on modern mobile devices.

This chapter is divided into two main sections. The first section is a quick overview of some of the benefits that TypeScript brings to the JavaScript development experience. The second section of this chapter deals with setting up a TypeScript development environment.

If you are an experienced TypeScript programmer, and you already have a development environment set up, then you might want to skip this chapter. If you have never worked with TypeScript before, and have picked up this book because you want to understand what TypeScript can do for you, then read on.

We will cover the following topics in this chapter:

  • The benefits of TypeScript

    • Compilation

    • Strong Typing

    • Integration with popular JavaScript libraries

    • Encapsulation

    • Private and public member variables

  • Setting up a development environment

    • Visual Studio

    • WebStorm

    • Brackets and Grunt

 

What is TypeScript?


TypeScript is both a language and a set of tools to generate JavaScript. It was designed by Anders Hejlsberg at Microsoft (the designer of C#), as an open-source project, to help developers write enterprise scale JavaScript. JavaScript has become widely adopted by programmers around the world – as it can run in any browser on any operating system. With the creation of Node, JavaScript can now also run on the server, desktop or mobile.

TypeScript generates JavaScript – it's as simple as that. Instead of requiring a completely new runtime environment, TypeScript generated JavaScript can re-use all of the existing JavaScript tools, frameworks, and wealth of libraries that are available for JavaScript. The TypeScript language and compiler, however, brings the development of JavaScript closer to a more traditional object-oriented experience.

EcmaScript

JavaScript as a language has been around for a long time, and is also governed by a language feature standard. The language defined in this standard is called ECMAScript, and each browser must deliver functions and features that conform to this standard. The definition of this standard helped the growth of JavaScript and the web in general, and allowed websites to render correctly on many different browsers on many different operating systems. The ECMAScript standard was published in 1999 and is known as ECMA-262, third edition.

With the popularity of the language, and the explosive growth of internet applications, the ECMAScript standard needed to be revised and updated. This process resulted in a draft specification for ECMAScript, called the fourth edition. Unfortunately, this draft suggested a complete overhaul of the language, and was not well received. Eventually, leaders from Yahoo, Google and Microsoft tabled an alternate proposal which they called ECMAScript 3.1. This proposal was numbered 3.1, as it was a smaller feature set of the third edition, and sat "between" edition 3 and 4 of the standard.

This proposal was eventually adopted as the fifth edition of the standard, and was called ECMAScript 5. The ECMAScript fourth edition was never published, but it was decided to merge the best features of both the fourth edition and the 3.1 feature set – into a sixth edition named ECMAScript Harmony.

The TypeScript compiler has a parameter that can be modified to target different versions of the ECMAScript standard. TypeScript currently supports ECMAScript 3, ECMAScript 5 and ECMAScript 6. When the compiler runs over your TypeScript, it will generate compile errors if the code you are attempting to compile is not valid for that particular standard. The team at Microsoft has also committed to follow the ECMAScript standards in any new versions of the TypeScript compiler, so as and when new editions are adopted, the TypeScript language and compiler will follow suit.

An understanding of the finer details of what is included in each release of the ECMAScript standard is outside of the scope of this book, but it is important to know that there are differences. Some browser versions do not support ES5 (IE8 is an example), but most do. When selecting a version of ECMAScript to target for your projects, you will need to consider which browser versions you will be supporting.

The benefits of TypeScript

To give you a flavor of the benefits of TypeScript (and this is by no means the full list), let's take a very quick look at some of the things that TypeScript brings to the table:

  • A compilation step

  • Strong or static typing

  • Type definitions for popular JavaScript libraries

  • Encapsulation

  • Private and public member variable decorators

Compiling

One of the most frustrating things about JavaScript development is the lack of a compilation step. JavaScript is an interpreted language, and therefore needs to be run in order to test that it is valid. Every JavaScript developer will tell horror stories of hours spent trying to find bugs in their code, only to find that they have missed a stray closing brace { , or a simple comma , - or even a double quote " where there should have been a single quote '. Even worse, the real headaches arrive when you misspell a property name, or unwittingly re-assign a global variable.

TypeScript will compile your code, and generate compilation errors where it finds these sort of syntax errors. This is obviously very useful, and can help to highlight errors before the JavaScript is run. In large projects, programmers will often need to do large code merges – and with today's tools doing automatic merges – it is surprising how often the compiler will pick up these types of errors.

While tools to do this sort of syntax checking – like JSLint – have been around for years, it is obviously beneficial to have these tools integrated into your IDE. Using TypeScript in a continuous integration environment will also fail a build completely when compilation errors are found – further protecting your programmers against these types of bugs.

Strong Typing

JavaScript is not strongly typed. It is a language that is very dynamic, as it allows objects to change their properties and behavior on the fly. As an example of this, consider the following code:

var test = "this is a string";
test = 1;
test = function(a, b) {
    return a + b;
}

On the first line of this code snippet, the variable test is bound to a string. It is then assigned a number, and finally is redefined to be a function that expects two parameters. Traditional object oriented languages, however, will not allow the type of a variable to change – hence they are called strongly typed languages.

While all of the preceding code is valid JavaScript - and could be justified - it is quite easy to see how this could cause runtime errors during execution. Imagine that you were responsible for writing a library function to add two numbers, and then another developer inadvertently re-assigned your function to instead subtract these numbers.

These types of errors may be easy to spot in a few lines of code, but it becomes increasingly difficult to find and fix these as your code base, and your development team grows.

Another feature of strong typing is that the IDE you are working in can understand what type of variable you are working with, and can bring better autocomplete or Intellisense options to the fore.

TypeScript's "syntactic sugar"

TypeScript introduces a very simple syntax to check the type of an object at compile time. This syntax has been referred to as "syntactic sugar", or more formally, type annotations. Consider the following TypeScript code:

var test: string = "this is a string";
test = 1;
test = function(a, b) { return a + b; }

Note on the first line of this code snippet, we have introduced a colon : and a string keyword between our variable and it's assignment. This type annotation syntax means that we are setting the type of our variable to be of type string, and that any code that does not use it as a string will generate a compile error. Running the preceding code through the TypeScript compiler will generate two errors:

error TS2011: Build: Cannot convert 'number' to 'string'.
error TS2011: Build: Cannot convert '(a: any, b: any) => any' to 'string'.

The first error is fairly obvious. We have specified that the variable test is a string, and therefore attempting to assign a number to it will generate a compile error. The second error is similar to the first, and is in essence saying that we cannot assign a function to a string.

In this way, the TypeScript compiler introduces strong, or static typing to your JavaScript code, giving you all of the benefits of a strongly typed language. TypeScript is therefore described as a "superset" of JavaScript. We will explore typing in more detail in the next chapter.

Type definitions for popular JavaScript libraries

As we have seen, TypeScript has the ability to "annotate" JavaScript, and bring strong typing to the JavaScript development experience. But how do we strongly type existing JavaScript libraries? The answer is surprisingly simple: by creating a definition file. TypeScript uses files with a .d.ts extension as a sort of "header" file, similar to languages such as C++, to superimpose strongly typing on existing JavaScript libraries. These definition files hold information that describes each available function and variable of the library, along with their associated type annotations.

Let's take a quick look at what a definition would look like. As an example, consider a function from the popular Jasmine unit testing framework called describe:

var describe = function(description, specDefinitions) {
  return jasmine.getEnv().describe(description, specDefinitions);
};

This function has two parameters, description and specDefinitions. Just reading this JavaScript, however, does not tell us what sort of parameters these are meant to be. Is the specDefinitions argument a string, or an array of strings, a function or something else? In order to figure this out, we would need to have a look through the Jasmine documentation found at http://jasmine.github.io/2.0/introduction.html. This documentation provides us with a helpful sample of how to use this function:

describe("A suite", function () {
    it("contains spec with an expectation", function () {
        expect(true).toBe(true);
    });
});

From the documentation, then, we can easily see that the first parameter is a string, and the second parameter is a function. There is nothing in the JavaScript language, however, that forces us to conform to this API. As mentioned before, we could easily call this function with two numbers – or inadvertently switch the parameters around, sending a function first, and a string second. We will obviously start getting runtime errors if we do this, but TypeScript – using a definition file – can generate compile time errors before we even attempt to run this code.

Let's take a look at a piece of the jasmine.d.ts definition file:

declare function describe(
    description: string, specDefinitions: () => void
): void;

This is the TypeScript definition for the describe function. Firstly, declare function describe tells us that we can use a function called describe, but that the implementation of this function will be provided at runtime.

Clearly, the description parameter is strongly typed to be of type string, and the specDefinitions parameter is strongly typed to be a function that returns void. TypeScript uses the double braces () syntax to declare functions, and the fat arrow syntax to show the return type of the function. So () => void is a function that does not return anything. Finally, the describe function itself will return void.

If our code were to try and pass in a function as the first parameter, and a string as the second parameter (clearly breaking the definition of this function) as shown in the following example:

describe(() => { /* function body */}, "description");

The TypeScript compiler will immediately generate the following errors:

error TS2082: Build: Supplied parameters do not match any signature of call target: Could not apply type "string" to argument 1 which is of type () => void

This error is telling us that we are attempting to call the describe function with invalid parameters. We will look at definition files in more detail in later chapters, but this example clearly shows that TypeScript will generate errors if we attempt to use external JavaScript libraries incorrectly.

Definitely Typed

Soon after TypeScript was released, Boris Yankov started a GitHub repository to house definition files, at DefinitelyTyped (https://github.com/borisyankov/DefinitelyTyped). This repository has now become the first port of call for integrating external libraries into TypeScript, and currently holds definitions for over 500 JavaScript Libraries.

Encapsulation

One of the fundamental principles of object-oriented programming is encapsulation: The ability to define data, as well as a set of functions that can operate on that data, into a single component. Most programming languages have the concept of a class for this purpose – providing a way to define a template for data and related functions.

Let's first take a look at a simple TypeScript class definition:

class MyClass {
    add(x, y) {
        return x + y;
    }
}

var classInstance = new MyClass();
console.log(classInstance.add(1, 2));

This code is pretty simple to read and understand. We have created a class, named MyClass, with a single function named add. To use this class, we simply create an instance of it, and call the add function with two arguments.

JavaScript, unfortunately, does not have a class keyword, but instead uses functions to reproduce the functionality of classes. Encapsulation through classes is accomplished by either using the prototype pattern, or by using the closure pattern. Understanding prototypes and the closure pattern, and using them correctly, is considered a fundamental skill when writing enterprise-scale JavaScript.

A closure is essentially a function that refers to independent variables. This means that variables defined within a closure function 'remember' the environment in which they were created. This provides JavaScript with a way to define local variables, and provide encapsulation. Writing the MyClass definition in the preceding code, using a closure in JavaScript would look something like this:

var MyClass = (function () {
    // the self-invoking function is the 
    // environment that will be remembered
    // by the closure
    function MyClass() {
        // MyClass is the inner function,
        // the closure
    MyClass.prototype.add = function (x, y) {
        return x + y;
    };
    return MyClass;
})();
var classInstance = new MyClass();
console.log("result : " + classInstance.add(1, 2));

We start with a variable called MyClass, and assign it to a function that is executed immediately – note the })(); syntax near the bottom of the code snippet. This syntax is a common way to write JavaScript in order to avoid leaking variables into the global namespace. We then define a new function named MyClass, and return this new function to the outer calling function. We then use the prototype keyword to inject a new function into the MyClass definition. This function is named add and takes two parameters, returning their sum.

The last two lines of the code show how to use this closure in JavaScript. Create an instance of the closure type, and then execute the add function. Running this in the browser will log result: 3 to the console, as expected.

Tip

Downloading the example code

You can download the example code files from your account at http://www.packtpub.com for all the Packt Publishing books you have purchased. If you purchased this book elsewhere, you can visit http://www.packtpub.com/support and register to have the files e-mailed directly to you.

Looking at the JavaScript code versus the TypeScript code, we can easily see how simple TypeScript looks, compared to the equivalent JavaScript. Remember how we mentioned that JavaScript programmers can easily misplace a brace {, or a bracket (? Take a look at the last line in the closure definition: })(); Getting one of these brackets or braces wrong can take hours of debugging to find.

TypeScript classes generate closures

The JavaScript closure as shown in the preceding code snippet, is actually the output of the TypeScript class definition. So TypeScript actually generates closures for you.

Note

Adding the concept of classes to the JavaScript language has been talked about for years, and is currently a part of the ECMAScript sixth Edition (Harmony) standard – but this is still a work in progress. Microsoft has committed to follow the ECMAScript standard in the TypeScript compiler, as and when these standards are published.

Public and private accessors

A further object-oriented principle that is used in encapsulation is the concept of data hiding – the ability to have public and private variables. Private variables are meant to be hidden to the user of a particular class – as these variables should only be used by the class itself. Inadvertently exposing these variables outside of a class can easily cause runtime errors.

Unfortunately, JavaScript does not have a native way of declaring variables private. While this functionality can be emulated using closures, a lot of JavaScript programmers simply use the underscore character _ to denote a private variable. At runtime though, if you know the name of a private variable – you can easily assign a value to it. Consider the following JavaScript code:

var MyClass = (function() {
    function MyClass() {
        this._count = 0;
    }
    MyClass.prototype.countUp = function() {
        this._count ++;
    }
    MyClass.prototype.getCountUp = function() {
        return this._count;
    }
    return MyClass;
}());

var test = new MyClass();
test._count = 17;
console.log("countUp : " + test.getCountUp());

The MyClass variable is actually a closure – with a constructor function, a countUp function and a getCountUp function. The variable _count is supposed to be a private member variable, one that is used only within the scope of the closure. Using the underscore naming convention gives the user of this class some indication that the variable is private, but JavaScript will still allow you to manipulate the variable _count. Take a look at the second last line of the code snippet. We are explicitly setting the value of the supposed private variable _count to 17 – which is allowed by JavaScript, but not desired by the original creator of the class. The output of this code would be countUp: 17.

TypeScript, however, introduces the public and private keywords that can be used on class member variables. Trying to access a class member variable that has been marked as private will generate a compile time error. As an example of this, the JavaScript code above can be written in TypeScript as follows:

class MyClass {
    private _count: number;
    constructor() {
        this._count = 0;
    }
    countUp() {
        this._count++;
    }
    getCount() {
        return this._count;
    }
}

var classInstance = new MyClass();
console.log(classInstance._count);

On the second line of our code snippet, we have declared a private member variable named _count. Again, we have a constructor, a countUp and a getCount function. If we compile this TypeScript code, the compiler will generate an error:

error TS2107: Build: 'MyClass._count' is inaccessible.

This error is generated because we are trying to access the private variable _count in the last line of the code.

The TypeScript compiler, therefore, is helping us to adhere to public and private accessors – by generating a compile error when we inadvertently break this rule.

Note

Remember, though, that these accessors are a compile-time feature only, and will not affect the generated JavaScript. You will need to bear this in mind if you are writing JavaScript libraries that will be consumed by third parties. The TypeScript compiler will also still generate the JavaScript output file, even if there are compile errors.

 

TypeScript IDEs


The purpose of this section is to get you up and running with a TypeScript environment so that you can edit, compile, run and debug your TypeScript code. TypeScript has been released as open-source, and includes both a Windows variant, and a Node variant. This means that the compiler will run on Windows, Linux, OS X, and any other operating system that supports Node.

On Windows environments, we can either install Visual Studio – which will register the tsc.exe (TypeScript Compiler) in our C:\Program Files directory, or we can use Node. On Linux and OS X environments, we will need to use Node. Either way, firing up a command prompt and typing tsc –v should display the current version of the compiler that we are using. Which at the time of writing, is version 1.4.2.0.

In this section, we will be looking at the following IDEs:

  • Visual Studio 2013

  • WebStorm

  • Brackets

Visual Studio 2013

First up, let's look at Microsoft's Visual Studio 2013. This is Microsoft's primary IDE, and comes in a variety of pricing combinations. At the top end is Ultimate, then Premium, then Professional, and finally Express. Ultimate, Premium and Professional all require paid licenses which range (at the time of writing) from $13,000 through to $1,199. The good news is that Microsoft has recently announced a Community Edition, which can be used in non-enterprise environments for both free and non-paid products. The TypeScript compiler is included in all of these editions.

Visual Studio can be downloaded as either a web-installer, or an .ISO CD image. Note that the web installer will require an internet connection during installation, as it downloads the required packages during the installation step. Visual Studio will also require Internet Explorer 10 or later, but will prompt you during installation, if you have not upgraded your browser as yet. If you are using the .ISO installer, just bear in mind that you may be required to download and install additional operating system patches if you have not updated your system with Windows Update in a while.

Creating a Visual Studio Project

Once Visual Studio is installed, fire it up and create a new project (File | New Project). Under the Templates section on the left hand side, you will see a TypeScript option. When this option is selected, you will be able to use a project template named Html Application with TypeScript. Enter a name and location for your project, and then click OK to generate a TypeScript project:

Visual Studio – selecting the TypeScript project type

Note

This is not the only project template that works with TypeScript. Any of the ASP.NET project types support TypeScript out of the box. If you are planning to use the Web API to provide RESTful data controllers, then you may consider creating an MVC Web Application from the start. Then, by simply including a TypeScript file, and specifying a .ts file extension within the project, Visual Studio will automatically start compiling your TypeScript files as part of the new project.

Default project settings

Once a new TypeScript project is created, notice that the project template generates a few files for us automatically:

  • app.css

  • app.ts

  • index.html

  • web.config

If we were to compile and then run this project now, we would have a complete, running TypeScript application right off the bat:

Visual Studio index.html running in Internet Explorer

Let's take a quick look at the generated index.html file and what it contains:

<!DOCTYPE html>

<html lang="en">
<head>
    <meta charset="utf-8" />
    <title>TypeScript HTML App</title>
    <link rel="stylesheet" href="app.css" type="text/css" />
    <script src="app.js"></script>
</head>
<body>
    <h1>TypeScript HTML App</h1>

    <div id="content"></div>
</body>
</html>

This is a very simple HTML file, which includes the app.css style sheet, as well as a JavaScript file named app.js. This app.js file is the JavaScript file that is generated from app.ts TypeScript file, when the project is compiled.

Note

The app.js file is not included in the Solution Explorer – only the app.ts TypeScript file is included. This is by design. If you wish to see the generated JavaScript file, simply click on the Show All Files button in the Solution Explorer toolbar.

Debugging in Visual Studio

One of the best features of Visual Studio is that it is truly an integrated environment. Debugging TypeScript in Visual Studio is exactly the same as debugging C# – or any other language in Visual Studio – and includes the usual Immediate, Locals, Watch and Call stack windows.

To debug TypeScript in Visual Studio, simply put a breakpoint on the line you wish to break on in your TypeScript file (Move your mouse into the breakpoint area next to the source code line, and click). In the image below, we have placed a breakpoint within the window.onload function.

To start debugging, simply hit F5.

Visual Studio TypeScript editor with a breakpoint set in the code

When the source code line is highlighted in yellow, simply hover your mouse over any of the variables in your source, or use the Immediate, Watch, Locals or Call stack windows.

Note

Visual Studio only supports debugging in Internet Explorer. If you have multiple browsers installed on your machine, make sure that you select Internet Explorer in your Debug toolbar, as shown in the following screenshot:

Visual Studio debug toolbar showing browser options

WebStorm

WebStorm is a popular IDE by JetBrains (http://www.jetbrains.com/webstorm/), and will run on Windows, Mac OS X and Linux. Prices range from $49 for a single developer to $99 for a commercial license. JetBrains also offers a 30 day trial version.

WebStorm has a couple of great features, including live-edit and code suggestions, or Intellisense. The live-edit feature allows you to keep a browser window open, which WebStorm will automatically update based on changes to CSS, HTML and JavaScript as you type it. Code suggestions – which are also available with another popular JetBrains product named Resharper – will highlight code that you have written, and suggest better ways of implementing it. WebStorm also has a large number of project templates. These templates will automatically download and include the relevant JavaScript or CSS files needed by the template, such as Twitter Bootstrap, or HTML5 boilerplate.

Setting up WebStorm is as simple as downloading the package from the website, and running the installer.

Creating a WebStorm project

To create a new WebStorm project, simply fire it up, and hit File | New Project. Select a Name, Location and Project type. For this project, we have chosen Twitter Bootstrap as the project type, as shown in the following screenshot:

WebStorm Create New Project dialog box

WebStorm will then ask you to select the version of Twitter Boostrap that you intend developing for. In this example, we have chosen version v3.2.0.

WebStorm Select Twitter Boostrap version dialog box

Default files

WebStorm has conveniently created a css, fonts and js directory as part of the new project – and downloaded and included the relevant CSS, font files and JavaScript files for us, in order to start building a new Bootstrap based website. Note that it has not created an index.html file for us, nor has it created any TypeScript files – as Visual Studio did. After a while working with TypeScript, most developers will delete these generic files anyway. So lets create an index.html file.

Simply click on File | New, select HTML file, enter index as a name, and click OK.

Next, let's create a TypeScript file in a similar manner. We will call this file app (or app.ts), to be the same as in the Visual Studio default project example. As we click inside the new app.ts file, WebStorm will pop up a green bar at the top of our edit window, with a suggestion reading File watcher 'TypeScript' is available for this file, as shown in the following screenshot:

WebStorm editing a TypeScript file for the first time showing the File Watcher bar

A WebStorm "file watcher" is a background process that will execute as soon as you have saved the file. This is equivalent to Visual Studio's Compile on save TypeScript option. As WebStorm suggests, now would be a good time to activate this file watcher for TypeScript. Click on the Add watcher link in the green bar, and fill in the details on the next screen.

We can leave the defaults on the next screen as they are for the time being, except for the Program setting:

If you are running on Windows, and already have Visual Studio installed, then this should be set to the full path of the tsc.exe executable, i.e. C:\Program Files (x86)\Microsoft SDKs\TypeScript\1.0\tsc.exe, as shown in the following screenshot:

If you are running on a non-windows box, or have installed TypeScript via Node, then this would just be set to tsc, with no path.

WebStorm new file watcher options screen

Now that we have a file watcher created for our TypeScript files, lets create a simple TypeScript class, which will modify the innerText of an HTML div. While you are typing, you will notice WebStorm's autocompletion or Intellisense feature helping you with available keywords, parameters, naming conventions and a host of other language specific information. This is one of the most powerful features of WebStorm, and is similar to the enhanced Intellisense seen in JetBrain's Resharper tool for Visual Studio. Go ahead and type the following TypeScript code, during which you will get a good feeling of WebStorm's available autocompletion.

class MyClass {
    public render(divId: string, text: string) {
        var el: HTMLElement = document.getElementById(divId);
        el.innerText = text;
    }
}

window.onload = () => {
    var myClass = new MyClass();
    myClass.render("content", "Hello World");
}

We start off with the MyClass class definition, which simply has a function called render. This render function takes a DOM element name, and a text string as parameters. It then simply finds the DOM element, and sets the innerText property. Note the use of strong typing on the variable el – we have explicitly typed this to be of the HTMLElement type.

We are also assigning a function to the window.onload event, which will execute once the page has been loaded, similar to the Visual Studio sample. Within this function, we are simply creating an instance of MyClass, and calling the render function with two string arguments.

If you have any errors in your TypeScript file, these will automatically show up in the output window, giving you instant feedback while you type. With this TypeScript file created, we can now include it in our index.html file, and try some debugging.

Open the index.html file, and add a script tag to include the app.js JavaScript file, along with a div with an id of "content". Just as we saw with TypeScript editing, you will find that WebStorm has powerful Intellisense features when editing HTML as well.

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <script src="app.js" type="application/javascript"></script>
</head>
<body>
    <h2>Index.html</h2>
    <div id="content"></div>
</body>
</html>

There are a couple of points to note in the preceding code. We are including a script tag for the app.js JavaScript file, as this is the output file that the TypeScript compiler will generate. We have also created an HTML <div> with an id of content that the instance of the MyClass class will use to render our text.

Running the web page in Chrome

When viewing or editing HTML files in WebStorm, you will notice a small set of browser icons popping up on the top right corner of the editing window. Clicking on any one of the icons will launch your current HTML page using the selected browser.

WebStorm editing an HTML file showing the popup browser launching icons

Debugging in Chrome

As we saw in Visual Studio, debugging in WebStorm is simply a matter of marking a breakpoint, and then hitting Alt + F5. WebStorm uses a Chrome Plugin to enable debugging in Chrome. If you do not have this plugin installed, WebStorm will prompt you the first time you start debugging, to download and enable the JetBrains IDE Support Chrome Plugin. With this plugin enabled, WebStorm has a very powerful set of tools to inspect JavaScript code, add watchers, view the console and many more, right inside the IDE.

WebStorm debugging session showing debugger panels

Brackets

The last IDE that we will look at in this chapter is not really an IDE for TypeScript, it is more of an IDE for web designers that has TypeScript editing capability. Brackets is an open-source code editor, and is really good at helping design and style webpages. Similar to WebStorm, it has a live editing mode where you can see changes to HTML or CSS on the running web page as you type. In our development teams, Brackets has become a very popular editor for rapid prototyping of HTML web pages and CSS styling.

There are a couple of reasons to include Brackets in this chapter. Firstly, it is completely open-source and therefore completely free – and it runs on Windows, Linux and Mac OS X. Secondly, using a Brackets environment shows what a bare-bones TypeScript environment would look like, with just a text editor and the command line. Lastly, Brackets shows that the syntax highlighting and code-completion capability of open-source projects can be just as good – if not faster than commercial IDEs.

Installing Brackets

Brackets can be downloaded with the preferred installers from http://brackets.io. Once installed, we will need to install some extensions. Brackets has a really slick and simple extension manager, which is easy to use, and which allows us to easily find and install available extensions. Any time an update to either Brackets, or one of your installed extensions is available, Brackets will automatically notify you.

To install an extension, fire up Brackets, and either click on File | Extension Manager, or click on the lego-block icon on the right-hand side vertical sidebar.

To start with, we will need to install the TypeScript extension. In the search bar, type brackets typescript, and install the Brackets TypeScript extension from Francois de Campredon.

As can be seen from the following screenshot, each extension has a More info… link – which will take you to the extension home page.

Brackets Extension manager interface

As well as the Brackets TypeScript extension, another useful extension is Code Folding by Patrick Oladimeji. This will allow you to collapse or expand sections of code in any file that you are editing.

Another great time-saver is Emmet by Sergey Chikujonok. Emmet (previously known as Zen Coding) uses a CSS-like short-hand, instead of traditional code snippets, to generate HTML. In this section, we will quickly show how Emmet can be used to generate HTML, just as a teaser. So go ahead and install the Emmet extension.

Creating a Brackets project

Brackets does not have the concept of a project per se, but instead just works off a root folder. Create a directory on your filesystem, and then open that folder in Brackets: File | Open Folder.

Let's now create a simple HTML page using Brackets. Select File | New, or Ctrl + N. With a blank file in front of us, we will use Emmet to generate our HTML. Type in the following Emmet string:

html>head+body>h3{index.html}+div#content

Now hit Ctrl + Alt + Enter, or from the File menu, select Emmet | Expand Abbreviation.

Voila! Emmet has generated the following HTML code in a millisecond - not bad for one line of source code:

<html>
<head></head>
<body>
    <h3>index.html</h3>
    <div id="content"></div>
</body>
</html>

Hit Ctrl + S to save the file, and enter index.html.

Note

Only once we have saved a file, does Brackets start to do syntax highlighting based on the file extension. This is true of any Brackets file, so once you have created a file – TypeScript, CSS or HTML, save it to disk as soon as you can.

Back to Emmet.

Emmet uses the > character to create a child, and the + character to denote a sibling. If you specify curly braces { } next to an element, this will be used as the text content.

The Emmet string that we entered previously basically said: "create an html tag with a child head tag. Then create another child tag of html named body, create a child h3 tag with the text "index.html", and then create a sibling div tag as a child of body with the id of content." Definitely head over to http://emmet.io for further documentation, and remember to keep the cheat-sheet handy (http://docs.emmet.io/cheat-sheet), when you are learning Emmet string shortcuts.

Now lets finish off our index.html with an app.js script to load our TypeScript generated JavaScript file. Move your cursor in-between the <head></head> tags, and type another Emmet string:

script:src

Now hit Ctrl + Alt + Enter, to have Emmet generate a <script src=""></script> tag, and conveniently place your cursor between the quotes ready for you to simply fill in the blanks. Now type the JavaScript filename, app.js.

Your completed index.html file should now look as follows:

<html>
<head>
    <script src="app.js"></script>
</head>
<body>
    <h3>index.html</h3>
    <div id="content"></div>
</body>
</html>

This is all we need for our sample HTML page.

Using Brackets live preview

Within Brackets, click on the live preview icon on the far right of the screen – it's the electric zig zag one – just above the lego-block packages icon. This will launch Chrome and render our index.html in live preview mode. Just to show how Brackets can be used for live preview, keep this Chrome window visible, and navigate back to Brackets. You should be able to see both windows at the same time.

Now edit the index.html file, and type the following Emmet shorthand under your <div id="content"></div> element:

ul>li.item$*5

Again, hit Ctrl + Alt + Enter, and note how the generated <ul> and <li> tags (5 of them) are automatically displayed in your Chrome browser. As you move your caret up or down in the source code, notice how the blue outline in Chrome shows the element in the web page.

Brackets running Chrome in live preview mode, showing highlighted elements

We won't be needing these <ul> <li> tags for our application, so simply Ctrl + Z, Ctrl + Z to undo our changes, or delete the tags.

Creating a TypeScript file

To create our very simple TypeScript application, hit Ctrl + N (new file), Ctrl + S (save file) and use app.ts as your file name. Start typing the following code, and notice how Brackets also does autocompletion, or Intellisense on the fly, similar to Visual Studio and WebStorm:

class MyClass {
    render( elementId: string, text: string) {
        var el: HTMLElement = document.getElementById(elementId);
        el.innerHTML = text;
    }
}
window.onload = () => {
    var myClass = new MyClass();
    myClass.render("content", "Hello world!");
}

This is the same code that we used previously, and simply creates a TypeScript class named MyClass that has a single render function. This render function gets a DOM element, and modifies it's innerHTML property. The window.onload function creates an instance of this class, then calls the render function with the appropriate parameters.

If you save the file by hitting Ctrl + S at any stage, Brackets will invoke the TypeScript language engine to verify our TypeScript, and render any errors in the bottom window pane. In the following screenshot, we can clearly see that we are missing a closing brace }.

Brackets editing a TypeScript file and showing compile errors

Brackets will not invoke the TypeScript compiler to generate an app.js file – it just parses the TypeScript code at this stage, and highlights any errors. Double-clicking on the error in the TypeScript Problem pane will jump to the line in question.

Compiling our TypeScript

Before we are able to run our application, we will need to compile the app.ts file into an app.js file by invoking the TypeScript compiler. Open up a Command Prompt, change to your source directory, and simply type:

tsc app.ts

This command will invoke the tsc command line compiler, and create an app.js file from our app.ts file.

Now that we have an app.js file in this directory, we can invoke the live preview button again, and now see that our TypeScript application has indeed rendered the Hello world! text as the innerHTML of the content div:

Brackets live preview running our TypeScript application

Using Grunt

Obviously, it is going to be very tedious to have to switch to the Command Prompt and manually compile each TypeScript file every time we have made a change. Grunt is an automated task runner (http://gruntjs.com) that can automate many tedious compile, build, and testing tasks. In this section, we will use Grunt to watch TypeScript files, and invoke the tsc compiler when a file is saved. This is very similar to WebStorm's file watch functionality that we used earlier.

Grunt runs in a Node environment. Node is an open-source, cross platform runtime environment, whose programs are written in JavaScript. To run Grunt, we will therefore need to install Node. Installers for Windows, Linux and OS X can be found from the Node website (http://nodejs.org/). Once Node is installed, we can use npm (Node package manager) to install Grunt and the Grunt command line interface.

Grunt needs to be installed as an npm dependency of your project. It cannot be installed globally, the way most npm packages can. In order to do this, we will need to create a packages.json file in the root project. Open up a Command Prompt, and navigate to the root directory of your Brackets project. Then simply type:

npm init

And follow the prompts. You can pretty much leave all of the options as their default, and always go back to edit the packages.json file that is created from this step, should you need to tweak any changes. With the package initialization step complete, we can now install Grunt as follows:

npm install grunt –save-dev

The -save-dev option will install a local version of Grunt in the project directory. This is done so that multiple projects on your machine can use different versions of Grunt. We will also need the grunt-typescript package, as well as the grunt-contrib-watch package. These can be installed with the following npm commands:

Npm install grunt-typescript –save-dev
Npm install grunt-contrib-watch –save-dev.

Lastly, we will need a GruntFile.js as the entry point for Grunt. Using Brackets, create a new file, save it as GruntFile.js, and enter the following JavaScript. Note that we are creating a JavaScript file here, not a TypeScript file. You can find a copy of this file in the sample source code that accompanies this chapter.

module.exports = function (grunt) {
    grunt.loadNpmTasks('grunt-typescript');
    grunt.loadNpmTasks('grunt-contrib-watch');
    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),
        typescript: {
            base: {
                src: ['**/*.ts'],
                options: {
                    module: 'commonjs',
                    target: 'es5',
                    sourceMap: true
                }
            }
        },
        watch: {
            files: '**/*.ts',
            tasks: ['typescript']
        }
    });

   //grunt.registerTask('default', ['typescript']);
    grunt.registerTask('default', ['watch']);
}

This GruntFile.js is necessary to setup all of the Grunt tasks. It is a simple function that Grunt uses to initialize the Grunt environment, and specify the Grunt commands. The first two lines of the function are loading grunt-typescript and grunt-contrib-watch tasks, and then runs the grunt.initConfig function with a configuration section. This configuration section has a pkg property, a typescript property and a watch property. The pkg property is set by reading the package.json file that we created earlier as part of the npm init step.

The typescript property has a base property, in which we are specifying that the source should be '**/*.ts' – in other words, all .ts files in any subdirectory. We are also specifying some TypeScript options – using 'commonjs' modules instead of 'amd' modules, and generating sourcemaps.

The watch property has two sub-properties. The files property specifies to watch for any .ts files in our source tree, and the tasks array specifies that we should kick off the TypeScript command once a file has been changed. Finally we call grunt.registerTask, specifying that the default task is to watch for file changes. Grunt will run in the background watching for saved files, and if found, will execute the TypeScript task.

We can now run Grunt from the command line. Make sure that you are in the Brackets project base directory, and fire up Grunt:

Grunt

Open up your app.ts file, make a small change (add a space or something), and then hit Ctrl + S to save. Now check back on the output from the Grunt command line. You should see something like this:

>> File "app.ts" changed.
Running "typescript:base" (typescript) task
2 files created. js: 1 file, map: 1 file, declaration: 0 files (861ms)
Done, without errors.
Completed in 1.665s at Fri Oct 10 2014 11:24:47 GMT+0800 (W. Australia Standard Time) - Waiting...

This command line output is confirmation that the Grunt watch task has identified app.ts has having changed, run the TypeScript task, created two files, and is now waiting for the next file to change. Flicking back to Brackets, we should now see the app.js file created by Grunt in the Brackets file pane.

Debugging in Chrome

Since Brackets is just being used as an editor, we will need to debug our applications using the standard Chrome development tools. One option that we specified in our GruntFile.js for TypeScript was to turn on sourcemaps (options { sourceMap : true }). With this option, Chrome – and other browsers – can map the running JavaScript back to the source TypeScript file. This means that you can set the debugger breakpoints in your TypeScript file, and walk through your TypeScript file while debugging.

To debug our sample app, firstly get the index.html page running in Live Preview mode, and hit F12 to bring up the development tools. Chrome has a number of tools available for developers, including Network, Console, and Elements to inspect the DOM. Click on the Sources tab and hit Ctrl + P to open a file. Scroll down to app.ts, and hit Enter. Put a breakpoint on line 9 ( var myClass = new MyClass()), and then re-load the page.

Chrome should pause the page in debugger mode as follows:

Brackets debugging TypeScript using Chrome development tools.

You can now use all of the Chrome debugging tools to your heart's content.

 

Summary


In this chapter we have had a quick look at what TypeScript is, and what benefits it can bring to the JavaScript development experience. We also looked at setting up a development environment using two popular commercial IDEs, and one open-source development environment. Now that we have a development environment setup, we can start looking at the TypeScript language itself in a bit more detail. We will start with types, move on to variables, and then discuss functions in the next chapter.

About the Author

  • Nathan Rozentals

    Nathan Rozentals has been writing commercial software for over 23 years. Starting with COBOL on mainframes, through C, onto C++, Java and finally settling on C# and ASP.NET.

    Nathan picked up TypeScript in October 2012 - a day after the 0.8.0 release - and could not put it down. In TypeScript he found a language that could bring all of the design patterns and practices he had learnt over the years - in a variety of languages - to JavaScript.

    Some 6 days after the 0.8.0 release, Nathan began blogging about TypeScript; covering a variety of topics, including Unit Testing, implementing an IoC Container, and Organizing your code with AMD Modules. He knew he had hit the mark when Microsoft themselves started to reference his blog in their CodePlex discussion forums

    Browse publications by this author

Latest Reviews

(1 reviews total)
Good
Book Title
Access this book and the full library for just $5/m.
Access now