TypeScript Namespaces

Organizing code with internal modules

📦 What are Namespaces?

Namespaces are TypeScript's way of organizing and grouping related code into logical containers, preventing naming conflicts and providing a structured approach to code organization in large applications.


// Simple namespace example
namespace Utilities {
  export function log(message: string) {
    console.log(message);
  }
}

Utilities.log('Hello from namespace!');
                                    

Output:

Hello from namespace!

Key Namespace Concepts

🏗️

Basic Namespace

Group related functionality

namespace MyApp {
  export class User {}
}
🔗

Nested Namespaces

Create hierarchical structure

namespace App {
  export namespace Utils {}
}
📤

Export Members

Make items publicly accessible

namespace Math {
  export function add() {}
}
🔀

Aliases

Create shortcuts for namespaces

import Utils = App.Utilities;
Utils.log('message');

🔹 Basic Namespace

Create a simple namespace to group related code:

// Define a namespace
namespace StringUtilities {
  // Export function to make it accessible
  export function capitalize(str: string): string {
    return str.charAt(0).toUpperCase() + str.slice(1);
  }
  
  export function reverse(str: string): string {
    return str.split('').reverse().join('');
  }
  
  // Private function (not exported)
  function helper() {
    return 'This is private';
  }
}

// Using namespace members
console.log(StringUtilities.capitalize('hello'));  // Output: Hello
console.log(StringUtilities.reverse('world'));     // Output: dlrow

// This would cause an error (helper is not exported)
// StringUtilities.helper();

Output:

Hello

dlrow

🔹 Nested Namespaces

Create hierarchical organization with nested namespaces:

namespace App {
  export namespace Models {
    export class User {
      constructor(public name: string, public age: number) {}
    }
    
    export class Product {
      constructor(public title: string, public price: number) {}
    }
  }
  
  export namespace Services {
    export class UserService {
      getUser(id: number) {
        return new Models.User('John', 30);
      }
    }
    
    export class ProductService {
      getProduct(id: number) {
        return new Models.Product('Laptop', 999);
      }
    }
  }
}

// Using nested namespaces
const user = new App.Models.User('Alice', 25);
const userService = new App.Services.UserService();
const fetchedUser = userService.getUser(1);

console.log(fetchedUser.name);  // Output: John

Output:

John

🔹 Multi-file Namespaces

Split namespaces across multiple files:

// File: validation.ts
namespace Validation {
  export interface StringValidator {
    isValid(s: string): boolean;
  }
}

// File: lettersValidator.ts
/// <reference path="validation.ts" />
namespace Validation {
  export class LettersOnlyValidator implements StringValidator {
    isValid(s: string): boolean {
      return /^[A-Za-z]+$/.test(s);
    }
  }
}

// File: numbersValidator.ts
/// <reference path="validation.ts" />
namespace Validation {
  export class NumbersOnlyValidator implements StringValidator {
    isValid(s: string): boolean {
      return /^[0-9]+$/.test(s);
    }
  }
}

// Usage
let lettersValidator = new Validation.LettersOnlyValidator();
console.log(lettersValidator.isValid('Hello'));  // true
console.log(lettersValidator.isValid('Hello123'));  // false

🔹 Namespace Aliases

Create shorter names for deeply nested namespaces:

namespace Company {
  export namespace Department {
    export namespace Engineering {
      export class Developer {
        constructor(public name: string) {}
        
        code() {
          return `${this.name} is coding`;
        }
      }
    }
  }
}

// Without alias (verbose)
let dev1 = new Company.Department.Engineering.Developer('Alice');

// With alias (cleaner)
import Dev = Company.Department.Engineering.Developer;
let dev2 = new Dev('Bob');

console.log(dev2.code());  // Output: Bob is coding

// Alias for nested namespace
import Eng = Company.Department.Engineering;
let dev3 = new Eng.Developer('Charlie');

Output:

Bob is coding

🔹 Namespace vs Modules

Understanding when to use namespaces vs ES6 modules:

// ❌ Namespace (older approach)
namespace MathUtils {
  export function add(a: number, b: number) {
    return a + b;
  }
}

// ✅ ES6 Module (modern approach - preferred)
// File: mathUtils.ts
export function add(a: number, b: number) {
  return a + b;
}

// File: main.ts
import { add } from './mathUtils';

// When to use Namespaces:
// - Legacy code
// - Global scope organization
// - Browser scripts without module bundler

// When to use Modules:
// - Modern TypeScript projects
// - Node.js applications
// - Projects with module bundlers (Webpack, Rollup)
// - Better tree-shaking and code splitting

🔹 Practical Example

Real-world namespace usage:

namespace Game {
  export namespace Characters {
    export class Player {
      constructor(
        public name: string,
        public health: number = 100
      ) {}
      
      attack(target: Enemy) {
        target.takeDamage(10);
      }
    }
    
    export class Enemy {
      constructor(
        public name: string,
        public health: number = 50
      ) {}
      
      takeDamage(amount: number) {
        this.health -= amount;
        console.log(`${this.name} took ${amount} damage. Health: ${this.health}`);
      }
    }
  }
  
  export namespace Utils {
    export function randomNumber(min: number, max: number): number {
      return Math.floor(Math.random() * (max - min + 1)) + min;
    }
    
    export function displayMessage(msg: string) {
      console.log(`[GAME]: ${msg}`);
    }
  }
}

// Using the game namespace
const player = new Game.Characters.Player('Hero');
const enemy = new Game.Characters.Enemy('Goblin');

Game.Utils.displayMessage('Battle started!');
player.attack(enemy);

const damage = Game.Utils.randomNumber(5, 15);
console.log(`Random damage: ${damage}`);

Output:

[GAME]: Battle started!

Goblin took 10 damage. Health: 40

Random damage: 12

🧠 Test Your Knowledge

What keyword makes namespace members accessible outside the namespace?