TypeScript Namespace with Internal Modules

Update: New and better Boilerplate that uses ES6 Modules in TypeScript check it out.

I am going to talk about JavaScript Namespacing with TypeScript’s Internal Modules and show an example how you can use namespacing with your TypeScript applications. If you are new to TypeScript check out my OOP TypeScript Tutorial.

First off JavaScript namespacing is a way of preventing issues or properties being overridden on the browser window object. It also keeps the browser window object cleaner because all our JavaScript object are not global. For example if I was to create a class called Main it would be window.Main and would be global. If someone else working on the same website as you creates a another Main JavaScript object then one of the Main object will be overriden with the other code.

What I have seen and have done myself is create a single property/variable and then add other objects to that property.

var somename = somename || {};
somename.Main = function(){};
somename.Car = function(){};

Now how do we do this in TypeScript? Lets take this TypeScript class below:

class Main
{
    constructor()
    {
        console.log("Main");
    }
}

If you compiled this code your window object property will look like:

window.Main

Now to add the Main class into a namespace we need to wrap the class with a module and give that module a name/namespace. The namespace can be anything you want and for example I am going to make the namespace MyNamespace. We also now need to put an export statement in front of our class declaration.

module MyNamespace
{
    export class Main
    {
        constructor()
        {
            console.log("Main");
        }
    }
}

Now your window object property will look like:

window.MyNamespace.Main

Import Other Namespace Classes

Lets take our Main class and now import some other classes that have a different namespace.

///<reference path='AnotherNamespace/ClassOne.ts'/>
///<reference path='AnotherNamespace/ClassTwo.ts'/>

module MyNamespace
{
    import ClassOne = AnotherNamespace.ClassOne;
    import ClassTwo = AnotherNamespace.ClassTwo;

    export class Main
    {
        private _classOne:ClassOne;
        private _classTwo:ClassTwo;

        constructor()
        {
            this._classOne = new ClassOne();
            this._classTwo = new ClassTwo();
        }
    }
}

You can see we reference two new classes with the reference path statement. Also when dealing with classes that have a different namespace you will need to use an import statement. The import statement(s) needs to be inside the module namespace area.

Here are the other classes for this example. Please not that they all have the same namespace but is different from the Main class. One thing to point out is if you are referencing classes with in the same namespace you do not need to use the import statement.:

///<reference path='CommonComponent.ts'/>

module AnotherNamespace
{
    export class ClassOne
    {
        private _component:CommonComponent;

        constructor()
        {
            this._component = new CommonComponent();
        }
    }
}
///<reference path='CommonComponent.ts'/>

module AnotherNamespace
{
    export class ClassTwo
    {
        private _component:CommonComponent;

        constructor()
        {
            this._component = new CommonComponent();
        }
    }
}
module AnotherNamespace
{
    export class CommonComponent
    {
        constructor()
        {
        }
    }
}

To compile all these classes into one file you can use the TypeScript compiler command below:

tsc -out _compiled/main.js Main.ts

Below is the HTML is for this TypeScript Namespace tutorial.

<!DOCTYPE html>
<html>
<head>
    <title></title>
    <script type="text/javascript" src="scripts/_compiled/main.js"></script>
    <script type="text/javascript">
        window.onload = function(event) {
            //Get class from namespace.
            var Main = MyNamespace.Main;

            var app = new Main();

            console.log(app);
            console.log("MyNamespace objects found on the window object:", window.MyNamespace);
            console.log("AnotherNamespace objects found on the window object:", window.AnotherNamespace);
        }
    </script>
</head>
<body>
    <p>Open your console log and view the output.</p>
</body>
</html>

You can download the example files here: https://github.com/codeBelt/Example-TypeScript-Namespace

Another Namespace Example

You can take this a step future and maybe it’s over kill. I am going you use reverse domain name notation and the window object property look like:

window.com.codebelt.Main
//Other Objects/Classes in my code base:
window.com.codebelt.components.vehicles.Truck
window.com.codebelt.components.accessories.soundsystems.CDPlayer

You may wanna check out my first TypeScript Tutorial to see the difference when not using TypeScript module’s.

///<reference path='com/codebelt/components/vehicles/Car.ts'/>
///<reference path='com/codebelt/components/vehicles/Truck.ts'/>

module com.codebelt
{
    import Car = com.codebelt.components.vehicles.Car;
    import Truck = com.codebelt.components.vehicles.Truck;

    export class Main
    {
        private _compact:Car;
        private _pickup:Truck;

        constructor()
        {
            this._compact = new Car(21, 18);
            this._compact.changeGear();

            this._compact.useAccessory();

            this._pickup = new Truck(16, 23);
            this._pickup.changeGear();
            this._pickup.useAccessory();

            this._compact.soundSystem.turnOn();
            this._compact.soundSystem.playSelection(2);
            this._pickup.soundSystem.turnOn();

            this._compact.drive();
            this._pickup.drive();
        }
    }
}

You can get this extreme namespacing example files at: https://github.com/codeBelt/Example-TypeScript-Namespace-Overboard

10 Responses to “TypeScript Namespace with Internal Modules”

  1. As with most examples of Typescript (including TypeScript.Org samples), I find it impossible to try these in Ie10. What am I missing about Typescript solutions in VS? No project files … no solution file?
    How can this example be loaded and run from VS2012 ?

    (I’m a C# developr)

    • I will have to talk with a co-worker if you they can show me how to in VS2012 but it maybe a few weeks before I write a tutorial.

  2. Someone needs to write an article … TypeScript in VS 2012 for the C# developer!

  3. this is awesome. thanks
    cp

  4. I like your typescript coding style – makes more sense to me than other styles I’ve seen.

    • Thanks! That is why I write these tutorials because some of the other tutorials are kind of confusing.

  5. Robert,
    Great article and sample code.

    One problem that I had was getting the code base to compile under –module commonjs (for NodeJS use). I tried exporting the main module also and that generated many reference errors.

    Any ideas how this could be done (as a single file, e.g., -out)? I

    • One simple way but unpleasant way to get it to work is compile as normal (tsc Main.ts -out ../bin/main.js). Then manually change two lines in the output code (main.js). Add exports, such as:

      })(exports.com || (exports.com = {}));
      var com = exports.com;

      as the last two lines. Then in create app.js in the bin directory:

      var m = require(‘./main.js’).com;
      var main = new m.codebelt.Main();

      and run it:
      node app.js

      A better way is needed.

  6. Hi, robert:
    Thanks for your sharing!
    And I have a Question:
    I found the project ‘StructureJS’ in your GitHub, I’m wondering why not use ‘///’ to include other classes instead of ‘import … from …’?

    Thanks!

Leave a Reply