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

Comments (Comment Moderation is enabled. Your comment will not appear until approved.)
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.