Typescript Tutorials | Typescript Namespace

javascript Aug 11, 2019

Typescript Namespace

Typescript Namespace can be used to group related features together. Each namespace is a singleton instance with all  its contents enclosed within the scope of the namespace. By grouping variables, functions, objects, classes, and interfaces into Typescript Namespace, you can keep them out of the global scope and avoid naming collisions, although the root of each namespace is added to the global scope.

Typescript Namespace are open ended and all declarations with the same name within a common root contribute toward a single namespace. This allows Typescript Namespace to be described in multiple files and will allow you to keep each file to a maintainable size.

below code shows two Typescript Namespace, both with a class named Example. Each namespace creates a separate context to allow the classes to have the same name. Each class is accessed as a member of the namespace, making the intended class unambiguous

namespace First {
    export class Example {
        log() {
      		  console.log('Logging from First.Example.log()');
        }
}
}
namespace Second {
    export class Example {
        log() {
            console.log('Logging from Second.Example.log()');
    }
    }
}
const first = new First.Example();
// Logging from First.Example.log()
first.log();
const second = new Second.Example();
// Logging from Second.Example.log()
second.log();

Typescript Namespaces can be organized into hierarchies: either by nesting them within each other, or by using a dotted-syntax when supplying the namespace identifier. These two alternatives are shown in with the first and second levels in the hierarchy being nested, and the third level being added using the dotted notation. In practical terms, all these declarations have added to the same hierarchy, as the calling code shows.

namespace FirstLevel {
	export namespace SecondLevel {
        export class Example {
        }
    }
}
namespace FirstLevel.SecondLevel.ThirdLevel {
    export class Example {
    }
}
const nested = new FirstLevel.SecondLevel.Example();
const dotted = new FirstLevel.SecondLevel.ThirdLevel.Example();

If you are using Typescript Namespaces, mixing the styles of hierarchical namespace organization, and appending to Typescript Namespaces across multiple files all adds to the psychological complexity of the program when it comes to fixing bugs or adding new behavior. The main driver for the hierarchy you create should be the ease of
locating functionality with the aid of autocompletion. A good hierarchy will make your code easier to find and reduce the need to cross reference documentation

You may have spotted that the nested module in code has an export keyword. This keyword marks a namespace member as public. Without the export keyword, the namespace member can only be accessed from within the namespace (including subsequent additions to the same namespace). This differs from classes where members are public by default. code below is a realistic example of the application of these different levels of visibility, with the exported public members appearing first, followed by variables and classes that are only for use within the namespace.

namespace Shipping {
// Available as Shipping.Ship
export interface Ship {
    name: string;
    port: string;
    displacement: number;
}
// Available as Shipping.Ferry
export class Ferry implements Ship {
    constructor(
    public name: string,
    public port: string,
    public displacement: number) {
    }
}

// Only available inside of the Shipping module
const defaultDisplacement = 4000;
class PrivateShip implements Ship {
constructor(
    public name: string,
    public port: string,
        public displacement: number = defaultDisplacement) {
        }
    }
}
const ferry = new Shipping.Ferry('Assurance', 'London', 3220);

The inverse of the export keyword is import. You can use an import statement to alias an item from another Typescript Namespace as shown in . The import statement references the Shipping.Ship class in the import statement and gives it the alias “Ship.” The alias can then be used throughout the Docking Typescript Namespace as a short name, so wherever Ship appears within the Typescript Namespace, it refers to Shipping.Ship. This is particularly useful if you have long names or deep nesting in your program as it allows you to reduce the length of annotations. This reduces the noise in your code that repeating the Typescript Namespace would cause. You can use any name in an import alias, although using a similar name to the imported member will make your code easier to comprehend.

namespace Docking {
    import Ship = Shipping.Ship;
    export class Dock {
        private dockedShips: Ship[] = [];
        arrival(ship: Ship) {
        this.dockedShips.push(ship);
        }
    }
}
const dock = new Docking.Dock();

The import alias can also be used outside of modules to provide short names.
There are a few differences between code editors and integrated development environments when it  comes to referencing Typescript Namespaces from other files. Visual Studio automatically includes all TypeScript files within the project in the compilation, which means you don’t need to specifically reference other files when
you refer to them. Other code editors require a hint to help them discover the source of the code you are depending on. The format for these hints is a reference comment, as shown in . Whether you need to use these hints or not, you will be responsible for making the code available at runtime.

///<reference path="Shipping.ts" />

There is one final feature of Typescript Namespaces to cover, which is declaration merging. On a simple level, any declaration that spans multiple blocks is a case of declaration merging, such as two interface blocks with the same name, which are merged into a single interface. Typescript Namespaces go beyond this simple merging by allowing merging with classes, functions, and enums. These hybrids may seem strange but represent an
incredibly common JavaScript pattern. code demonstrates declaration merging between a Typescript Namespace and a class. Both the class and namespace have the same name, which causes the merge. This allows code to instantiate a new instance of
the class, or of members from the namespace.

// Class/Namespace Merging
class Car {
}
namespace Car {
    export class Engine {
    }
    export class GloveBox {
    }
}
const car = new Car();
const engine = new Car.Engine();
const gloveBox = new Car.GloveBox();

Neeraj Dana

Experienced Software Engineer with a demonstrated history of working in the information technology and services industry. Skilled in Angular, React, React-Native, Vue js, Machine Learning