Check out our Angular Book Series.

Create TypeScript Modules - - Part 8

This is the last in my series of articles intended to introduce you to Typescript. It is bonus material I wrote for my Angular 4 book. This is the last part of the series. Check out part 1, part 2, Part 3, Part 4, Part 5. and Part 6, and Part 7.

When writing a real-world application, it does not make sense to include all the code in a single file. TypeScript supports that by allowing you to expand different functionality into modules.

Create Interface Module

The first thing we're going to do is create a module for the name interface. I put this in a file named IFile.ts:


export interface name {
firstName: string;
middleInitial? : string;
lastName: string;
getName() : string;
};

This looks exactly like the Interface created in the previous exception with the one addition of the export keyword. Export tells the compiler that this class is available for use inside other classes.

Create Class Modules

Now create the Person class:


export class Person implements name {
firstName: string;
middleInitial : string;
lastName: string;
getName() : string {
return this.firstName + ' ' + this.middleInitial + ' ' + this.lastName;
}
}

This also puts the export keyword in front of the class definition. If you try this you'll notice an immediate error. The name is not defined. To define it we'll need to add an import statement:


import {name} from "./IName";

The import statement tells you that the name entity is imported from the IName file and can be used within this class. The path I used, './IName', tells us that the files are in the same directory, however we can use a more elaborate package setup, and most likely you will do that for main applications.

We can create the Pets.ts module in the same manner:


import {name} from "./IName";

export class Pet implements name {
firstName: string;
lastName: string;
type : string;
getName() : string {
return this.firstName + ' ' + this.lastName + ", " + this.type;
}
}

This code mirrors the Person module, with the primary changes being the use of the export keyword before the class definition and the import of the name interface.

The Echo class needs a similar rework:


import {name} from "./IName";

export class Echo {
static readonly messageIntro : string = "Hello"
subjectArray : name[];
private message : string;
constructor(subjects : name[]){
this.subjectArray = subjects;
}
createMessage():void{
this.message = '';
for (let person of this.subjectArray){
this.message += Echo.messageIntro + " " + person.getName() + "<br/>";
}
}
echo():string{
return this.message;
}
}

The functionality remains unchanged. Like the previous classes it uses an export statement to make the class available elsewhere, and an import statement to make use of the name interface.

Rework Main Application

With all the classes stored in separate files, our primary app has become a lot simpler. First, import all the classes:


import {name} from "./IName";
import {Person} from "./Person";
import {Pet} from "./Pet";
import {Echo} from "./Echo";

Then, create the nameArray:


let nameArray : name[] = [];

Now, populate the nameArray:


let jeffryInstance : Person = new Person();
jeffryInstance.firstName = "Jeffry";
jeffryInstance.middleInitial = "A";
jeffryInstance.lastName = "Houser";
nameArray.push(jeffryInstance);

let hercInstance : Pet = new Pet();
hercInstance.firstName = "Hercules";
hercInstance.lastName = "Houser";
hercInstance.type = "Dog";
nameArray.push(hercInstance);

let zeusInstance : Pet = new Pet();
zeusInstance.firstName = "Isadora";
zeusInstance.lastName = "Houser";
zeusInstance.type = "Dragon";
nameArray.push(zeusInstance);

Create an instance of the Echo class:


let echoInstance : Echo = new Echo(nameArray);

Call the createMessage() function:


echoInstance.createMessage();

Finally, output the results:


document.body.innerHTML = echoInstance.echo();

The changes here was, primarily, removing the class and interface definitions and replacing them with imports.

Setup Module Loader

The import statement is not a native JavaScript statement and does not have an easy parallel. To make code like this work in the browser we'll need to use a module loader. There are a few different types of module loaders such as RequireJS or SystemJS. Many people use code tools like Browserify or WebPack to encapsulate away the complexity.

For the purposes of this sample, I'm going to use RequireJS. Open up the index.html file and add this script statement:


<script data-main="requireconfig"
src="//cdnjs.cloudflare.com/ajax/libs/require.js/2.3.4/require.min.js">

</script>

This loads the RequireJS library from a remote CDN. Note that I have completely removed the script tag that loads the hello.js file. The script tag also has a different attribute named data-main with a value of requireconfig. This property tells Require that whenever it has completed loading it should look for the requireconfig.js file. Create that file next:


requirejs.config({
baseUrl: '',
paths: {
app: ''
}
});

This sets up the baseUrl and the paths to the app. Since all our code is in the main dev directory, I set these values to blank. Now, tell RequireJS to load our main application file:


requirejs(['hello']);

Since there are a few different methods of creating modules, we have to tell our TypeScript compiler which one to use. We want it to use the amd approach. When you compile your application add the module flag and specify amd. Use this at the command line:


tsc module amd hello

You'll see this:

Now load the app in the browser:

Congratulations! This series should have given you all the information you need to know to start using TypeScript to build your applications. Check out our book on Angular 4 which uses TypeScript heavily.

Keep up to date by reading DotComIt's Monthly Technical Newsletter

Create an Interface in TypeScript - - Part 7

I'm writing a series of articles about Typescript as extra material to support my upcoming Angular 4 book. This is the seventh part of that series. Check out part 1, part 2, Part 3, Part 4, Part 5. and Part 6.

This section will talk about interfaces. It is not about User interfaces, but rather object-oriented interfaces. An interface is a definition of properties and methods that must be supported by a class which implements this interface. You can think of an interface as the contract between a class instance and a method argument or variable. If they both match the interface they are interchangeable.

Create the Interface

For this sample, we're going to create a name interface. This interface will represent the name of a person and will contain a first name and last name. It will have an optional middle initial and also a method to retrieve the name. Here is the interface:


interface name {
firstName: string;
middleInitial? : string;
lastName: string;
getName() : string;
}

The interface is set up similar to a class or enum. It uses the keyword interface, and the name of the interface--in this case name. The firstName and lastName properties are as normal properties on an object. The middleInitial is an optional property, and that is distinguished by a question mark. Finally, a single method is defined by the interface, getName(). This will be used to return the name. The interface does not contain an implementation, just a definition of the method. That means different classes which extend the interface can have different implementations.

Rework the Echo Class

Let's rework the Echo class to use the interface instead of strings. First create the method stub with the instance variables:


class Echo {
static readonly messageIntro : string = "Hello"
subjectArray : name[];
private message : string;
}

The main change here is that the subject string was replaced with a subjectArray of name types. The constructor:


constructor(subjects : name[]){
this.subjectArray = subjects;
}

The constructor now accepts an array of name instead of a single string. The createMessage() function now loops over the array:


createMessage():void{
this.message = '';
for (let person of this.subjectArray){
this.message += Echo.messageIntro + " " + person.getName() + "<br/>";
}
}

Inside the loop, the interface's getName() function is used to add an element to the output. Finally, the echo() function:


echo():string{
return this.message;
}

The echo function has not changed, it just returns the object instance variable, message.

Implement the Interface with a Class

I'm going to create two classes which implement our name interface contract. One will be for a Person and another for a Pet. First, the Person class:


class Person implements name {
firstName: string;
middleInitial : string;
lastName: string;
getName(): string {
return this.firstName + ' ' + this.middleInitial + ' ' + this.lastName;
}
}

The class is defined with the class keyword followed by the name of the class. Then comes the implements keyword followed by the name of the interface. If you wanted you could list multiple interfaces here.

The firstName, middleInitial, and lastName are created properties on the object, not much different than how they were with the interface definition. The getName() method includes a definition. It concatenates the firstName, middleInitial, And lastName, returning a single string. Now, let's create another class that implements name. This one is called Pet:


class Pet implements name {
firstName: string;
lastName: string;
type : string;
getName(): string {
return this.firstName + ' ' + this.lastName + ", " + this.type;
}
}

This includes the firstName and lastName defined as variables on the class object. A new property is named type, this will represent the type of pet we have. A class can implement properties or methods not included in an interface. The middleInitial is left out, which is okay because that is marked as an optional property in the interface--and my pets don't have middle initials. The getName() method puts together the firstName and lastName, but appends the type to the end.

Create a name Array

We have an interface and two classes that extend it. Let's put all together. Start by creating a names array:


let nameArray : name[] = [];

Now create a new Person instance. This one represents me:


let jeffryInstance : Person = new Person();
jeffryInstance.firstName = "Jeffry";
jeffryInstance.middleInitial = "A";
jeffryInstance.lastName = "Houser";
nameArray.push(jeffryInstance);

The new jeffryInstance of the Person class is added to the nameArray.

Create two pets:


let hercInstance : Pet = new Pet();
hercInstance.firstName = "Hercules";
hercInstance.lastName = "Houser";
hercInstance.type = "Dog";
nameArray.push(hercInstance);

let zeusInstance : Pet = new Pet();
zeusInstance.firstName = "Isadora";
zeusInstance.lastName = "Houser";
zeusInstance.type = "Dragon";
nameArray.push(zeusInstance);

One is for my pet dog, Hercules, and the other is for my pet dragon, Isadora. Both are added to the same nameArray value without issue even though they have different types. The implementation of the interfaces tells the compiler that the nameArray can accept both Pet and Person instances.

Now, create an instance of the Echo class:


let echoInstance : Echo = new Echo(nameArray);

Create the message:


echoInstance.createMessage();

And output the message:


document.body.innerHTML = echoInstance.echo();

Recompile the app and load it in a browser:

It works as expected.

I have one more entry into this introduction to TypeScript series. It will tell you how to create Modules from your class and interface files.

Keep up to date by reading DotComIt's Monthly Technical Newsletter

Create your first TypeScript Class - - Part 6

I'm writing a series of articles about Typescript as extra material to support my upcoming Angular 4 book. This is the sixth part of that series. Check out part 1, part 2, Part 3, Part 4, and Part 5.

This entry will teach you about creating your own classes. A class is like your own variable type with data and functions to process that data.

Create a Class

Create your class stub:


class Echo {
}

This creates a class named Echo. The purpose of this class is to create and store our welcome message. Let's start by creating some properties on the class:


static readonly messageIntro : string = "Hello"
subject : string;
private message : string;

The subject is a relatively normal variable. It is a string that contains the subject of our welcome message. The message is similar, but has the private distinguisher. This means that the message variable is private to the local message. It will contain the final message once it is put together, but is only accessible inside the class, not from code accessing an instance of the class.

The messageIntro is a bit different. We are not able to define constants inside of a TypeScript class, so instead I used the readonly keyword. This means the value will not be changeable, just like a constant. I also define the messageIntro as a static property, which means it exists on the class and not on an instance of the class.

Every class needs a constructor, so create one:


constructor(subject : string){
this.subject = subject;
}

The constructor will be called automatically when we create a new instance of the class with the new keyword. This constructor accepts one argument, the subject. The code just saves the subject argument into the subject variable.

Now, add a createMessage() function:


createMessage():void{
this.message = Echo.messageIntro + " " + this.subject + "<br/>";
}

This concatenates the read only messageIntro variable with the subject and a line break. We had similar code in previous samples, but not encapsulated into a function. The return type of this function is void, meaning nothing is returned.

We'll add one final function to our class:


echo():string{
return this.message;
}

This function returns the complete message. The message value could be blank if the createMessage() function as not called yet, however this will still work.

Now, create an instance of the Echo class:


var echoInstance : Echo = new Echo('World')

This uses the new keyword to create the new instance. You may have seen this in other languages. You can output the subject for testing purposes:


console.log(echoInstance.subject);

You can also try to output the message:


console.log(echoInstance.message);

Since the message is a private variable, you'll see a compile error:

By the same token, we can access the messageIntro static value:


console.log(echoInstance.messageIntro);
console.log(Echo.messageIntro);

Can you guess which line works before trying to compile the code? The second one is the proper way to access static variables. The first one will throw an error:

Our final code is to output the value to the screen:


document.body.innerHTML = echoInstance.echo();

Compile the code--you should see no errors--and load it in a browser:

In a non-sample application, I might try to make my classes more discrete. Since this one adds a line break at the end of the message, it is conflating data processing and display code, something which is undesirable in real world applications.

Review the Generated Code

This is the generated code:


var Echo = (function () {
function Echo(subject) {
this.subject = subject;
}
Echo.prototype.createMessage = function () {
this.message = Echo.messageIntro + " " + this.subject + "<br/>";
};
Echo.prototype.echo = function () {
return this.message;
};
Echo.messageIntro = "Hello";
return Echo;
}());
var echoInstance = new Echo('World');
echoInstance.createMessage();
document.body.innerHTML = echoInstance.echo();

The Echo class is created using an immediately invoked function expression. The static class property is created as an instance variable inside the class--remember that JavaScript doesn't have the concept of readonly or static properties. The subject and message variables are not defined since they do not have default values. They'll be created on the class when they are needed, which is inside the function.

Although beyond the scope of this tutorial, inheritance is supported with TypeScript, so one class can inherit from another.

Keep up to date by reading DotComIt's Monthly Technical Newsletter

Loops and Arrays in TypeScript - Part 5

I'm writing a longer series of articles about Typescript. This will be extra material to support my upcoming Angular 4 book. This is the fifth part of that series. Check out part 1, part 2, Part 3, and Part 4.

This entry will focus on loops and arrays. We'll create an array of strings, and then loop over them with our echo function to welcome multiple people in our HTML page.

Create an Array

The first step is to create an array. You can use this sytnax:


let personArray : string[] = ["Jeffry", "Tom", "John"];

This creates a variable just like other variables we had seen. The key differentiator is that after the type, I added square brackets. This is what tells the compiler we are creating an array of strings. You can define arrays with any of the native types, such as numbers or Boolean, or with your own custom types.

For-in Loop

The very first time I wanted to loop over an array, I used a for-in loop, like this:


let bodyString : string = "";
for (let person in personArray){
bodyString += echo(messageIntro + " " + person + "<br/>");
}
document.body.innerHTML = bodyString ;

I had used for-in loops in other languages, such as ActionScript so this was my natural impulse.

Let's look at the results:

Instead of outputting the data in the array, it outputted the index. The proper way to use a for-in loop in TypeScript would be like this:


for (let person in personArray){
bodyString += echo(messageIntro + " " + personArray[person] + "<br/>");
}

This isn't much different than a generic for loop that uses a counter, although the syntax is a bit nicer:

All version of ECMAScript after 2015 support for-in loops the same way that TypeScript does. This is supported by most browsers and in fact that generated JS Code uses for-in loops:


for (var person in personArray) {
bodyString += echo(messageIntro + " " + person + "<br/>");
}

But, this result wasn't quite what I was after. Thankfully TypeScript includes another option, the for-of loop.

For-Of Loops

A for-of loop makes one syntactical difference than a for-in loop. Instead of using the keyword in, it uses the keyword on:


for (let person of personArray){
bodyString += echo(messageIntro + " " + person + "<br/>");
}

This type of loop the loop counter, person, will match the value of the personArray instead of the index. After the compilation this is turned into a for loop with an explicit counter:


for (var _i = 0, personArray_1 = personArray; _i < personArray_1.length; _i++) {
var person = personArray_1[_i];
bodyString += echo(messageIntro + " " + person + "<br/>");
}

Compile this code and load it in the browser to see the expected results:

Looping in TypeScript is not much different than looping in other languages.

The next entry in this series will focus on creating classes.

Keep up to date by reading DotComIt's Monthly Technical Newsletter

String Enums in TypeScript - Part 4

I'm writing a longer series of articles about Typescript. This will be extra material to support my upcoming Angular 4 book. This is the fourth part of that series. Check out part 1, part 2, and Part 3. This article will focus on creating String based Enums.

What is an Enum?

Enums are a data type I have not come across in most other languages, but they are inspired by C#. An enum is a way to give friendly names to numerical or string values. They are like an array with indexes, but more specific. I can envision using something like this with a view stack style component and using an enum to handle which view is currently displayed. Or, I might use it with an event class instance to determine what type of event occurred. Or it could be used to determine what color style to apply to certain text.

Create a String based Enum

It is interesting that Enum's can be used to represent textual values too. Look at this:


enum MyColors {
Blue = "#0000FF",
Red = "#FF0000",
Green = "#00FF00",
};

The value of the color name represents the hex value of the actual color. I recently could have used something similar when dynamically applying colors to the header of a site based on which section the user was viewing. Get the individual colors, and output them:


let myColor1 :MyColors = MyColors.Blue;
let myColor2 :MyColors = MyColors.Red;
let myColor3 :MyColors = MyColors.Green;

console.log(myColor1);
console.log(myColor2);
console.log(myColor3);

You'll see something like this:

Enums are an interesting data type, caught somewhere between an array and a class.

Keep up to date by reading DotComIt's Monthly Technical Newsletter

Enums in TypeScript - Part 3

I'm writing a longer series of articles about Typescript. This will be extra material to support my upcoming Angular 4 book. This is the third part of that series. Check out part 1 and part 2. This article will focus on Enums, a TypeScript data type that does not exist in JavaScript.

What is an Enum?

Enums are a data type I have not come across in most other languages, but they are inspired by C#. An enum is a way to give friendly names to numerical values. They are like an array with indexes, but more specific. I can envision using something like this with a view stack style component and using an enum to handle which view is currently displayed. Or, I might use it with an event class instance to determine what type of event occurred. Or it could be used to determine what color style to apply to certain text.

Create a Number based Enum

I'm going to start by creating a simple sample with a number based enum:


enum MyNumbers {
First,
Second,
Third
}

The MyNumbers enum contains four values each one representing a number. Since enums are sort of like arrays, the First item is at the 0 index, the second item will have the value of 1, and so on. We can use MyNumbers like it was it's own variable type:


let myNum :MyNumbers = MyNumbers.First;

Output this value.


console.log(myNum);

What do you think you'll get? Since it is the value of MyNumbers.First and that is the first element of the zero-based index, you'll get number 0:

A benefit of enums is that we can control the number scheme:


enum MyNumbers {
First = 1,
Second,
Third
}

We specified the First item is equal to the number 1. Turn each element into a variable:


let myNum1 :MyNumbers = MyNumbers.First;
let myNum2 :MyNumbers = MyNumbers.Second;
let myNum3 :MyNumbers = MyNumbers.Third;

Then output them:


console.log(myNum1);
console.log(myNum2);
console.log(myNum3);

You'll see:

Now our text numbers match up with the actual text index. We can control the numbers even if they aren't in sequential order. Add a new entry to the MyNumbers enum:


enum MyNumbers {
First = 1,
Second,
Third,
Ten = 10,
}

This is number 10, skipping four through 9. Grab it as a variable and output it:


let myNum10 :MyNumbers = MyNumbers.Ten;
console.log(myNum10);

Combined with our other outputs, you'll see something like this:

Enums provide a lot of flexibility.

Enums can also be created to use a string based index, and we'll discuss that in the next article.

Keep up to date by reading DotComIt's Monthly Technical Newsletter

Creating Variables in TypeScript - Part 2

I'm working on a longer series of articles about Typescript. This will be extra material to support my upcoming Angular 4 book. This is the second part of that series. Check out part 1.

An important part of programming is the ability to create variables. Let's turn our "Hello World" Variable into a variable. First, we'll do it the Javascript way and then we'll modify it with some TypeScript.

Create a Variable

This is the original demo from the previous section:


function echo(message) {
return message;
}
document.body.innerHTML = echo("Hello World");

We can easily add a variable in here. First, create the variable:


var message ="Hello World"

The var keyword is the normal way to create a variable in JavaScript. Now, modify the echo() call to pass the variable instead of the string:


document.body.innerHTML = echo(message);

Recompile the code and it will work just as the previous sample:

Define the Variable with Let instead of Var

TypeScript includes a secondary way to create a variable, using the let keyword instead of the var keyword:


let message ="Hello World";

This simple replaces the var command with the let command. Recompile and you'll see the same results. Let is part of the ECMAScript 6 standard, but for maximum compatibility, you probably want to stick to ECMAScript 5 or lower compatibility.

The reason to use the let command instead of var is because the two scope differently. When you use var the new variable is created as part of the function block. If the variable is not part of the function block it is added to the global scope of the page. This is why it is considered a best practice for a lot of code to be included in an IIFE. This can cause unexpected results in some cases, such as when you access loop counters inside nested for loops, or have one function embedded in another. The let keyword always scopes at the block level, so each for loop would be considered its' own block.

Consider this code:


function scopedemovar(){
for(var i = 0; i <10; i++){
console.log('outer i: ' + i);
for(var i = 0; i <10; i++){
console.log('inner i: ' + i);
}
}
}
scopedemovar();

Although this might be considered nonstandard code because the counter variable for both loops is defined twice and identical it is still perfectly valid. What would you expect the output to be? Try it and run it:

You may expect the outer loop to loop 10 times, but it only loops once. That is because the inner loop changes the value of the counter variable and the stop condition triggers the second time the outer loop tries to run.

Change the var to let:


function scopedemolet(){
for(let i = 0; i <10; i++){
console.log('outer i: ' + i);
for(let i = 0; i <10; i++){
console.log('inner i: ' + i);
}
}
}

Now, each i variable is scoped to its own for block and they do not interfere with each other:

I cut off the full output since it was very long, but you can run the code to see that both the inner and outer loop both execute a full 10 times using the let value.

Add Typing to Variables

An important decision for using TypeScript is to make variables statically typed instead of dynamically typed. We can add a type to the variable definition, like this:


let message : string ="Hello World";

We can change the function definition too:


function echo(message:string ):string {
return message;
}

The function now includes a typed argument and an explicit return type. When we send in the message variable the compiler checks to make sure that we are sending in a string. Recompile the code and run it. You'll see no differences in the output:

Open up the JavaScript file created by the TypeScript compiler for a bit of a surprise:


function echo(message) {
return message;
}
var message = "Hello World";
document.body.innerHTML = echo(message);

All your type statements were stripped out. That is because these types are part of TypeScript, but not JavaScript. They allow for compile time checking of values, but do not change the underlying language or how things run in the browser. This is an important distinction to remember as you learn TypeScript. The language is all about improved tooling and compile time validation; not about a new language in the browser.

Keep up to date by reading DotComIt's Monthly Technical Newsletter

Introduction to TypeScript - Part 1

I'm working on a longer series of articles about Typescript. This will be extra material to support my upcoming Angular 2 book. This is the first part of that series.

What is TypeScript?

TypeScript is a strongly typed language which can be used to build web applications. It come with a special compiler that converts the strongly typed language into JavaScript so it can run in a web browser. Since TypeScript is strongly typed, it can offer better tooling than can be used with simple JavaScript. Angular 2 was built using TypeScript and I use it heavily in my Angular 4 book. This article is intended to give you an introduction to TypeScript.

Setup the Project

The first step to creating a TypeScript application is to install the compiler. I'm going to use the Node compiler. First, you'll need to set up the node project. Run this command:


npm init

And follow the instructions. You'll see something like this:

This will create a package.json file that will look something like this:


{
"name": "01helloworld",
"version": "1.0.0",
"description": "Sample TypeScript Project",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Jeffry Houser",
"license": "ISC"
}

Now install the TypeScript compiler:


npm install -g typescript

You'll see this:

With TypeScript installed, you're ready to write your first Typescript application.

Create Your First TypeScript File

Create a file named hello.ts:


function echo(message) {
return message;
}
document.body.innerHTML = echo("Hello World");

The purpose of this code is to echo a Hello Word message. The function accepts a string, and returns it. The innerHTML of the document's body tag is set to the results of the function call.

This file would be valid JavaScript, but it works fine since TypeScript is a Superset of JavaScript. We can use JavaScript inside of TypeScript easily. We'll improve on this throughout the article as we introduce more TypeScript specific concepts.

You can compile this file by running this command line:


tsc hello

You'll see something like this:

You aren't given a lot of feedback, but if you check the directory, you'll see a hello.js file:


function echo(message) {
return message;
}
document.body.innerHTML = echo("Hello World");

There isn't a lot of difference between the original file and the compiled file, that is because our main TypeScript file is primarily JavaScript. This is a place to start and over the series we'll expand our TypeScript knowledge.

Test the Application in a Browser

Now it is time to test the application in a browser. Create a page named Index.html:


<html>
<head><title>TypeScript Greeter</title></head>
<body>
<script src="hello.js"></script>
</body>
</html>

This index file loads the hello.js file, which will cause the document.body.innerHTML assignment to be called, which will run function and return the results:

Congratulations! You've created your first TypeScript application.

Keep up to date by reading DotComIt's Monthly Technical Newsletter

Compile Code on the Fly - TypeScript and Gulp - Part 2

This is the second in a series of articles no compiling TypeScript applications with Gulp. Check out Part 1 which covers most of the setup; or sign up below to get our fully detailed white paper.

Gulp allows us to automatically run a gulp task when a certain directory changes. This is built in and we don't need an additional plugin to make it happen. We're going to make a task which will watch for TypeScript files for changes, and then trigger the buildTS task again.

First, let's create a variable to point at the TypeScript source:


var typeScriptSource = [sourceRoot + "/**/*.ts"];

The sourceRoot variable was created in the previous article, and points to the src directory. The wild cards tell Gulp to look at all subdirectories inside the sourceRoot folder.

Now create a gulp task called buildWatch:


gulp.task('buildWatch', ['buildTS'], function(){
});

You'll notice that there are three arguments to this gulp task, something we hadn't seen before. The first is the task name, buildWatch. The second is an array of strings with each string represents a gulp task. These tasks will run before the third argument's function is executed. Here we are only running one task, buildTS, before starting the buildWatch task.

Here is the function code:


gulp.watch(typeScriptSource,['buildTS']).on('change', function(event){
console.log('Event Type' + event.type);
console.log('File Path' + event.path);
})

We use the watch() function on the Gulp object. It accepts two arguments. The first argument is a source array, in this case the typeScriptSource value. The second argument is a task array. In this case just the buildTS task. Reading this in English, it says watch for files that match typeScriptSource, and when something changes run the buildTS task. Dot notation is used to daisy chain an 'on' method to the watch. When the change event occurs, the type of event and modified files are output to the console.

Run this script:


gulp buildWatch

You'll see something like this:

The important thing to notice is that the console does not go back to a command prompt; the code is left running in the background. Change some code to see what happens:

As you save files, the script automatically notices, and reruns the appropriate task. You'll get console information about the file that has changed.

Overall, I find the watch task to be a very powerful development tool.

Yes, I want to get your white paper on building TypeScript applications

Building HTML5 Applications with TypeScript and Gulp - Part 1

TypeScript is a newish language for application development on the web. It is a superset of JavaScript, and supports things like static typing and class based object oriented programming. Static typing, particularly, can offer improved tooling over what is currently available for simple JavaScript programming.

TypeScript can be used for any web application, or even on the server side with NodeJS. It is the recommended language for Angular 2 applications. TypeScript is compiled to regular JavaScript for deployment and testing. This white paper will explain the infrastructure we use to make this happen.

The TypeScript Application

Before we start to look at the build process, let's look at a super simple TypeScript application. We'll need some code to compile. This code borrows heavily from the official TypeScript tutorials. It will add a 'hello world' message to the body of an HTML page.

Create a directory for this setup. The final directory setup will look something like this:

This is a description of each directory:

  • TypeScriptAndGulp_Article: The root directory will contain the script files for running Gulp and config file for NodeJS.
    • build: This directory will contain the final, processed, build.
    • node_modules: This directory will contain the NodeJS package, such as Gulp and TypeScript, to needed to perform the actions.
    • src: This directory will contain the application's source files.

We will create most of these files and directories as we move through the process.

For now, I named the project directory TypeScriptAndGulp_Article. Start by creating the src directory. I always separate the source code, compiled code, build scripts, and NodeJS modules. Inside the src directory, create an index.html file:


<html>
<head>
<title>TypeScript Sample for DotComIt Article</title>
</head>
<body>
<script src="sample.min.js"></script>
</body>
</html>

This is a simple index.html file. There is one item I want to draw attention to. The script tag which imports a JavaScript file named sample.min.js. This is the file we will generate from the TypeScript code.

Next, create a file named greeter.ts. The ts extension is the standard extension for TypeScript files, similar to how 'js' is the standard extension for JavaScript files. For this sample I'll put all the files inside the root of the src directory, however in a more complex application, I may categorize the files under a descriptive directory structure.

This is the greeter.ts:


export function sayHello(name: string) {
return `Hello from ${name}`;
}

This file exports a function named sayHello(). The export is not something you'll commonly see in browser JavaScript, but is used when creating NodeJS Modules. It, basically, says that "This is an API I Want people to use to access code in this file." The sayHello() method has a single parameter, name. The type of the name is specified, something that doesn't happen in JavaScript but adding it allows for type checking at the compiler level. The body of the method returns a string, referencing the name variable inside the string. The syntax is very similar to JavaScript, so learning TypeScript should not be a big hurdle for you to climb.

Now create a file named main.ts. This is the entry point to our application. Back in my school days we'd call the routine that ran the app a main routine, so this is a similar approach. The first thing the main.ts does is import the greeter file:


import { sayHello } from "./greeter";

This makes all the code from the greeter.ts file available to use in the main.ts file. Now, create a showHello() method:


function showHello(name: string) {
document.body.innerHTML = sayHello(name);
}

This method looks a lot like a JavaScript method definition, the only difference is that the name variable is given a type of string. The code accesses the innerHTML of the web pages body tags and outputs the results of the sayHello method, which will just be a string that says hello from the given name.

Finally, call the showHello() method:


showHello("World");

That completes the super simple TypeScript application. I could write a lot about TypeScript, however I wanted this article to focus on the build process of turning TypeScript into a JavaScript web application. As such, I'll leave the JavaScript there. When you finally compile the application, it should look something like this in the browser:

A Basic Compile Script

To compile TypeScript into JavaScript we are going to use NodeJS and a bunch of plugins.

Install and Setup NodeJS

The first step is to install NodeJS if you haven't already. The formal instructions will give you more detailed instructions if you haven't already done so. Then create a generic package.json configuration file. You can run this script:


npm init

And follow the instructions to create a simple package.json. You'll see something like this:

My final package.json is listed below:


{
"name": "typescriptandgulp",
"version": "1.0.0",
"description": "A sample project to compile TypeScript with Gulp",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Jeffry Houser",
"license": "ISC",
"repository": {}
}

Install Node Modules

Now we want to install some NodeJS plugins. First, we want to make sure Gulp is available. Gulp is the script runner we'll use to execute tasks to run our application. Run this command:


npm install --save-dev gulp

You'll see a screen similar to this:

You can ignore the warnings. Your project directory will now have a node_modules directory.

Next, install the TypeScript plugin:


npm install --save-dev typescript

The NodeJS TypeScript plugin will not be used directly in the gulp script, but is a required dependency:

Next, install browserify. Browserify will combine all the JavaScript files into a single file. We also want tsify installed, a plugin that will allow browserify to compile TypeScript into JavaScript. First, install browserify:


npm install --save-dev browserify

You'll see results like this:

Then install tsify:


npm install --save-dev tsify

Your screen should look like this:

A Gulp stream object is named vinyl and is a virtual file format. To manipulate the output from Browserify with a Gulp script , we'll need to convert Browserify's object to the vinyl format. Thankfully there is a plugin for that, vinyl-source-stream module:


npm install --save-dev vinyl-source-stream

See the console results:

It is a lot of setup, but we should have all the required plugins we need to get started now.

Create the Gulp Task

In the root directory of the project, create a file named gulpfile.js. It is the default Gulp configuration file.

First, load the gulp module:


var gulp = require("gulp");

From there, you can create a gulp task for compiling TypeScript:


gulp.task("buildTS", function () {
});

This is a blank task that does nothing. It calls the task() method on the gulp object. The task() method has two argument: the name of the task and a function to perform the task. You can execute this task by typing this into your console:


gulp buildTS

You should see something like this:

The task does nothing yet, though. Let's make it do something. Import the rest of the libraries:


var browserify = require("browserify");
var source = require('vinyl-source-stream');
var tsify = require("tsify");

Make sure these libraries are imported outside of the Gulp task. After the library import, still outside the Gulp task, let's define a few variables. The first is something I call appEntry:


var appEntries = ['src/main.ts']

It is an array that contains the main TypeScript file. Browserify will analyze main.ts to find all other files it uses and will do recursively. This is a bit different than the process I used in an AngularJS JavaScript application; where I'd process all files ending with the js extension.

Next, create a variable for the processed file name, and one for the final path:


var javaScriptDestinationFile = 'sample.min.js';
var destinationPath = 'build';

The destination file is the final output after the TypeScript files are merged and compiled into a single one. We referenced this file name in the index.html document. The second variable specifies the final destination of the file. I could define these as part of the Gulp task, but prefer to define them as global variables so they are easily accessible across multiple tasks, and I can tweak how everything works just by changing the config values. Now go back inside the buildTS task and call the browserify() method:


return browserify({
compilerOptions: {
module: "commonjs",
target: "es5",
},
entries: appEntries
})

This calls the browserify() method and passes in an argument. The argument object specifies the configuration for this browserify process. Let's go through them:

  • compilerOptions: This is another object that specifies how the TypeScript compiler will work.
    • module: Specifies how modules are loaded in UI code, in this case we are using the commonjs convention.
    • target: Specifies the ECMAScript version you want to output to; in this case I am specifying EcmaScript 5, however other versions are supported.
  • entries: Specifies an array of entry points to your application.

This is a very simple config, and it can be a lot more complicated if you need it to be. Next, tell Browserify to compile the TypeScript code:


.plugin(tsify)

Each successive command is daisy chained on the other with the dot syntax. This uses the Browserify plugin() method to call the tsify package to compile the TypeScript code into JavaScript.

Next, call bundle() to merge all code into a single unit:


.bundle()

This one is simple. Then, specify the name of the new file:


.pipe(source(javaScriptDestinationFile))

This uses the vinyl-source-stream module to turn the javaScriptDestinationFile name into something that can be accessed via Gulp. The pipe() method means that we are getting ready to output information, instead of processing input. Finally, specify the destination of the new file:


.pipe(gulp.dest(destinationPath));

This uses the pipe() operator too; and the value is Gulp's dest() function. This, basically, tells the script to put all our files in the build directory.

You can run the gulp script:

Look at the directory structure after our first run:

All the node modules we installed are in the node_modules directory. The source we looked at earlier is in the src directory. The JavaScript file built from the TypeScript files is in the build directory. The gulpfile.js and package.json are in the root application directory. I like this structure because it cleanly separates concerns.

Things are not yet runnable in a browser, because the Index.html was not moved from the src directory to the build directory. For the sake of this article, you can move it manually. Runt he code in the browser, and you should see this:

This isn't an interesting app, but it does prove that Gulp is successfully compiling TypeScript and copying the HTML files from the source directory into the build directory.

What's Next?

The next article in this blog series will focus on how to write a Gulp Script that will watch for any changes to your TypeScript files, and re-compile them as you change code.

If you want a more in depth tutorial, sign up to get our full 30 page white paper on building TypeScript applications with Gulp.

Yes, I want to get your white paper on building TypeScript applications

All Content Copyright 2005, 2006, 2007, 2008, 2009 Jeffry Houser. May not be reused without permission
BlogCFC was created by Raymond Camden. This blog is running version 5.9.2.002.