RequireJS

TypeScript example using RequireJS

1. TypeScript with RequireJS

In this article we are going to explain how to create a TypeScript application and separate its components in modules. After that we are going to show how to load these modules using AMD with RequireJS and the TypeScript compiler options to support it.
All code and examples used in this tutorial are available in the download section at the end of this article.
Before starting with the article you need to install NodeJS in your system. Instructions can be found here: https://nodejs.org/en/.

2. RequireJS

RequireJS is an AMD JavaScript library that supports asynchronous file and module loading. It is optimized for web browser usage but it is also possible to use in Java or Node environments. It is compatible with all main browsers and quite intuitive to use. Its main benefit is that it offers the option to logically structure an application following the AMD principles.

In the article https://www.webcodegeeks.com/javascript/requirejs/requirejs-tutorial-how-to-use-requirejs/ you can find more information about how to use RequireJS.
 

3. TypeScript

TypeScript is a free and open source programming language created and supported by Microsoft. It enhances basic JavaScript with Object Oriented capabilities like object typing and classes support. Applications writen in TypeScript need to be transcompiled to JavaScript. The compiler is called tsc and code written in TypeScript can be compiled to JavaScript in almost any JavaScript engine like NodeJS or a Browser, in this example we are going to use NodeJS to compile the application.

As we said before we are going to install TypeScript using NodeJS, in order to do that, you can type:

npm install -g typescript

To check that the installation has been successfull please type tsc in your console and something like the following should appear:

Version 1.8.10
Syntax:   tsc [options] [file ...]

Examples: tsc hello.ts
          tsc --out file.js file.ts
          tsc @args.txt

Options:
 --allowJs                           Allow javascript files to be compiled.
 --allowSyntheticDefaultImports      Allow default imports from modules with no default export. This does not affect code emit, just typechecking.
 --allowUnreachableCode              Do not report errors on unreachable code.
 --allowUnusedLabels                 Do not report errors on unused labels.
 -d, --declaration                   Generates corresponding '.d.ts' file.
...

A good explanation and overview about TypeScript can be found in https://en.wikipedia.org/wiki/TypeScript.

4. Creating a TypeScript project with NodeJS

In order to create our application we type the following

npm init 

and we accept all options that are prompted (in case you want to modify some, fell free to do it).

We edit the package.json file and include the following to indicate a TypeScript dependency:

package.json

//check download section to see JS code
"dependencies": {
    "typescript": "^1.8.10"
  }

After that we edit again the package.json and add a new script to run the TypeScript compiler tsc:

package.json

//check download section to see complete JSON
 "scripts": {
    "test": "test",
    "tsc_amd": "tsc --module amd Game.ts"
  },

We will explain later what options we are passing to the compiler.

5. Modules in TypeScript

Modules is all about scoping. That is classes, methods, functions, etc. declared in the scope of a module are not visible outside this scope. In order to make them visible they need to be exported. The same applies for using this variable, function, class, method, whatever outside this module: it needs to be imported.

Modules features can be exported in one of the following ways:

    • using the keyword export, like in:

nofile.js

//check download section to see similar JS code
export const name = "dani";
    • using export statements, for example:

nofile.js

//check download section to see similar JS code
class Saluter{
    hi(s: string) {
        return "hello " + name;
    }
}
export { Saluter};
export { Saluter as MySaluter };
    • using export =, in this case import let = require("module") needs to be used. This option will be used in the article. For example:

nofile.js

//check download section to see similar JS code
class Salute{
    hi(s: name) {
        return "hello " + name;
    }
}
export = Salute;

nofile.js

//check download section to see similar JS code
import salute = require("./Salute");
let saluter= new salute();
console.log(saluter.hi("Dani");

Imports can be done in one of the following ways:

    • Import a single export from a module

nofile.js

//check download section to see similar JS code
import { Salute} from "./Salute";

let salute = new Salute();
    • Import the entire module into a single variable, and use it to access the module exports

nofile.js

//check download section to see similar JS code

import * as saluter from "./Salute";
let sal = new saluter.Salute();

Once we know how to create modules in TypeScript and how to export and import them and their properties, we need to generate them by indicating the tsc compiler what module target we are going to use. Possible targets are:

  • CommonJS (for NodeJS apps)
  • AMD / RequireJS
  • UMD
  • SystemJS
  • ECMAScript 2015 native modules

The target is indicated to the compiler with the option --module, like:

tsc --module  

In this article we are going to show how to generate modules for AMD RequireJS based applications. This can be done by typing:

tsc --module amd 

In order to generate just one output file the option outFile can be used in combination with the --module amd shown before.

This is just a brief explanation to support our example. For more information about modules in TypeScript please visit https://www.typescriptlang.org/docs/handbook/modules.html.

6. Example

In this chapter we are going to apply all this theory. We are going to create a TypeScript application divided in different files containing different modules that need to work with each other. Then we are going to launch the application without any module target and we are going to see what happens. Finally we are going to generate the application to run using RequireJS as module target using the compiler options explained before.

Here are some of the classes used in the application (you can download all of them in the download section of this article). Game.ts contains the code needed to play a game between two teams:

Game.ts

//check download section to see JS code
import Team = require("Team");

class Game{
    home: Team;
    away: Team;
    date: number;//epoch
    location: string;


    constructor(home?:Team, away?:Team, date?: number, location?: string){
        if(home != null){
            this.home = home;
        }else{
            this.home = new Team();
        }

        if(away != null){
            this.away = away;
        }else{
            this.away = new Team();
        }

        if(date != null){
            this.date = date;
        }else{
            this.date = 1000;
        }

        if(location != null){
            this.location = location;
        }else{
            this.location = 'Carlos Tartiere, Oviedo';
        }
    }

    toString(){
        return this.home.name + " against " + this.away.name + " at " + this.date + " in " + this.location;
    }
}

export = Game;

Team.ts containing a coach, a director and a bunch of players per team:

Team.ts

//check download section to see JS code
import Coach = require("Coach");
import Director = require("Director");
import Player = require("Player");

class Team {

    name: string;
    coach:Coach;
    director:Director;
    players:[Player];

    generateRandomPlayers() {
        this.players = [new Player(), new Player(), new Player(), new Player(), new Player(), new Player(), new Player(), new Player(), new Player(), new Player(), new Player()];
    }

    constructor() {
        this.name="Real Oviedo";
        this.coach = new Coach();
        this.director = new Director();
        this.generateRandomPlayers();
    }

}

export = Team;

A Player abstraction:

Player.ts

//check download section to see JS code
import Person = require("Person");

class Player implements Person {
    firstName: string;
    lastName: string;
    age: number;
    country: string;
    goals: number;
    caps: number;

    constructor (){
        this.firstName = "Andres";
        this.lastName = "Iniesta";
        this.age = 31;
        this.country = 'Spain';
        this.goals = 22;
        this.caps = 100;
    }
}

export = Player;

Here we show a small snippet from the index.html where the require.js file is launched and initialized using the configuration file main.js and the game is initialized and started by requiring its entry point using RequireJS require function and calling its main method. Other files are not shown since they do not add any value to the article, as said, you can download them at the end of this tutorial:

index.html

//check download section to see JS code

<script src="require.js" data-main="main.js"></script>
</body>
<button class="play" value="play" onclick="play();">play</button>

<script>
    function play() {
        require(['Game'], function (Game) {
            var game = new Game();
            console.log(game.toString());
        });
    }

</script>

We can generate the application typing:

npm run tsc_amd

This launches the tsc compiler with the needed options to generate AMD RequireJS compatible JavaScript files, as stated in our package.json file. Now we can launch the index.html in our browser, click the button and check what happens in the console. I recommend to debug the application to check what files are loaded and how the files have been generated.

In combination with --module amd you can use --outFile file to combine all output in one file, something like:

tsc --module amd --outFile GameCompact.js Game.ts

So all required content is available in the new file GameCompact.js. The tsc options listed above can be entered in the package json file as a new script. This provides us more flexibility. Here is how the npm configuration package.json file looks like (I repeat, everything can be found in the archived file at the end of the article):

package.json

//check download section to see JS code
{
  "name": "teams",
  "version": "1.0.0",
  "description": "teams",
  "main": "main.js",
  "scripts": {
    "test": "test",
    "tsc_amd_one": "tsc --module amd --outFile GameCompact.js Game.ts",
    "tsc_amd": "tsc --module amd Game.ts"
  },
  "author": "dani",
  "license": "ISC",
  "dependencies": {
    "typescript": "^1.8.10"
  },
  "devDependencies": {}
}

7. Options

TypeScript compiler tsc supports a large list of options and parameters. In this article we only made use of a few of them in order to generate AMD RequireJS compatible modules. If you are interested in all the available options that the TypeScript compiler supports, please visit https://www.typescriptlang.org/docs/handbook/compiler-options.html.

8. Download

Download
In the following link you can download a full working example covering the main components explained in this article: RequireJSTypeScriptExample

9. Links

The following links contain more information and references about the topics mentioned in this article:

Dani Buiza

Daniel Gutierrez Diez holds a Master in Computer Science Engineering from the University of Oviedo (Spain) and a Post Grade as Specialist in Foreign Trade from the UNED (Spain). Daniel has been working for different clients and companies in several Java projects as programmer, designer, trainer, consultant and technical lead.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

1 Comment
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Martin Herløv Andersen
Martin Herløv Andersen
7 years ago

Thanks for the article.

I am trying to introduces typescript in a javascript project that is using amd. Do you know of a way to use typescript with old amd modules?

http://stackoverflow.com/questions/42552364/using-amd-modules-with-typescript

Back to top button