+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Part 134 of 354

🏢 Namespace Basics: Organizing Code

Master TypeScript namespaces to create organized, hierarchical code structures with clean encapsulation and logical grouping of related functionality 🚀

🚀Intermediate
25 min read

Prerequisites

  • Understanding of TypeScript modules and basic syntax 📝
  • Knowledge of interfaces, classes, and functions ⚡
  • Familiarity with JavaScript object structures 💻

What you'll learn

  • Master namespace syntax and declaration patterns 🎯
  • Create organized code hierarchies with logical grouping 🏗️
  • Implement namespace merging and advanced features 🐛
  • Build maintainable codebases with clean encapsulation ✨

🎯 Introduction

Welcome to the corporate headquarters of TypeScript code organization! 🏢 If modules were like separate office buildings each with their own address, then namespaces are like having different departments within the same building - accounting, marketing, engineering - all under one roof but clearly separated and organized!

Namespaces provide a way to organize code into logical groups within a single module. While modern TypeScript development primarily uses ES6 modules, namespaces still serve important purposes for organizing related functionality, creating libraries, and maintaining large codebases. They offer a powerful mechanism for creating hierarchical structures and avoiding naming conflicts.

By the end of this tutorial, you’ll be a namespace expert, capable of creating well-organized, maintainable code structures that make large applications easy to navigate and understand. Let’s explore the art of hierarchical code organization! 🌟

📚 Understanding Namespaces

🤔 What Are Namespaces?

Namespaces are a way to organize code by grouping related functionality under a common identifier. They create a hierarchical structure that helps prevent naming conflicts and provides logical organization for large codebases.

// 🌟 Basic namespace declaration
namespace MyCompany {
  export interface Employee {
    id: number;
    name: string;
    department: string;
  }

  export class EmployeeManager {
    private employees: Employee[] = [];

    addEmployee(employee: Employee): void {
      this.employees.push(employee);
    }

    getEmployee(id: number): Employee | undefined {
      return this.employees.find(emp => emp.id === id);
    }
  }

  export function validateEmployee(employee: Employee): boolean {
    return employee.id > 0 && employee.name.length > 0;
  }

  // Internal (non-exported) functionality
  const COMPANY_NAME = 'My Company Inc.';
  
  function generateEmployeeId(): number {
    return Math.floor(Math.random() * 10000);
  }
}

// ✨ Using namespace members
const employee: MyCompany.Employee = {
  id: 1,
  name: 'John Doe',
  department: 'Engineering'
};

const manager = new MyCompany.EmployeeManager();
manager.addEmployee(employee);

const isValid = MyCompany.validateEmployee(employee);

// 🎯 Namespace vs Module comparison
// Namespace (internal organization)
namespace Utils {
  export namespace String {
    export function capitalize(str: string): string {
      return str.charAt(0).toUpperCase() + str.slice(1);
    }
    
    export function truncate(str: string, length: number): string {
      return str.length > length ? str.slice(0, length) + '...' : str;
    }
  }

  export namespace Number {
    export function round(num: number, decimals: number): number {
      return Number(num.toFixed(decimals));
    }
    
    export function isEven(num: number): boolean {
      return num % 2 === 0;
    }
  }
}

// Usage: Clear hierarchical access
const title = Utils.String.capitalize('hello world');
const shortText = Utils.String.truncate('This is a long text', 10);
const rounded = Utils.Number.round(3.14159, 2);

// Module (external organization)
// Would be in separate files:
// string-utils.ts: export function capitalize(str: string): string { ... }
// number-utils.ts: export function round(num: number, decimals: number): number { ... }
// index.ts: export * from './string-utils'; export * from './number-utils';

// 🏗️ Advanced namespace features
namespace AdvancedExample {
  // 📊 Namespace can contain various types of declarations
  export interface Config {
    apiUrl: string;
    timeout: number;
  }

  export type Status = 'pending' | 'success' | 'error';

  export enum Priority {
    LOW = 1,
    MEDIUM = 2,
    HIGH = 3,
    CRITICAL = 4
  }

  export class Task {
    constructor(
      public id: string,
      public title: string,
      public priority: Priority = Priority.MEDIUM
    ) {}

    getStatusMessage(): string {
      return `Task ${this.id}: ${this.title} (Priority: ${Priority[this.priority]})`;
    }
  }

  export namespace Validators {
    export function validateConfig(config: Config): boolean {
      return config.apiUrl.length > 0 && config.timeout > 0;
    }

    export function validateTask(task: Task): boolean {
      return task.id.length > 0 && task.title.length > 0;
    }
  }

  // 🔧 Internal utilities (not exported)
  const DEFAULT_TIMEOUT = 5000;
  
  function logDebug(message: string): void {
    if (process.env.NODE_ENV === 'development') {
      console.log(`[DEBUG] ${message}`);
    }
  }

  // 📦 Factory functions
  export function createTask(title: string, priority?: Priority): Task {
    const id = generateTaskId();
    logDebug(`Creating task with ID: ${id}`);
    return new Task(id, title, priority);
  }

  export function createConfig(apiUrl: string, timeout?: number): Config {
    return {
      apiUrl,
      timeout: timeout || DEFAULT_TIMEOUT
    };
  }

  function generateTaskId(): string {
    return `task_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
  }
}

// 🎮 Let's create a comprehensive namespace management system
console.log('🏢 Namespace Organization Examples');

// 🏗️ Namespace analyzer and organizer
namespace NamespaceAnalyzer {
  // 📊 Track namespace statistics
  export interface NamespaceStats {
    name: string;
    memberCount: number;
    exportedMembers: number;
    nestedNamespaces: number;
    interfaces: number;
    classes: number;
    functions: number;
    types: number;
    enums: number;
  }

  export interface NamespaceStructure {
    name: string;
    path: string[];
    members: NamespaceMember[];
    children: NamespaceStructure[];
    parent?: NamespaceStructure;
  }

  export interface NamespaceMember {
    name: string;
    type: 'interface' | 'class' | 'function' | 'type' | 'enum' | 'const' | 'namespace';
    isExported: boolean;
    signature?: string;
    dependencies: string[];
  }

  // 📈 Namespace registry
  const namespaceRegistry = new Map<string, NamespaceStructure>();
  const memberUsage = new Map<string, number>();

  // 🔍 Analyze namespace structure
  export function analyzeNamespace(namespaceName: string): NamespaceStats {
    console.log(`🔍 Analyzing namespace: ${namespaceName}`);

    // 🎯 Simulate namespace introspection
    const structure = getNamespaceStructure(namespaceName);
    
    const stats: NamespaceStats = {
      name: namespaceName,
      memberCount: structure.members.length,
      exportedMembers: structure.members.filter(m => m.isExported).length,
      nestedNamespaces: structure.children.length,
      interfaces: structure.members.filter(m => m.type === 'interface').length,
      classes: structure.members.filter(m => m.type === 'class').length,
      functions: structure.members.filter(m => m.type === 'function').length,
      types: structure.members.filter(m => m.type === 'type').length,
      enums: structure.members.filter(m => m.type === 'enum').length
    };

    console.log(`📊 Analysis complete:`, stats);
    return stats;
  }

  // 🗂️ Get namespace structure
  function getNamespaceStructure(namespaceName: string): NamespaceStructure {
    // 🎯 Simulate namespace structure discovery
    const structure: NamespaceStructure = {
      name: namespaceName,
      path: [namespaceName],
      members: [
        {
          name: 'User',
          type: 'interface',
          isExported: true,
          signature: 'interface User { id: string; name: string; }',
          dependencies: []
        },
        {
          name: 'UserService',
          type: 'class',
          isExported: true,
          signature: 'class UserService { ... }',
          dependencies: ['User']
        },
        {
          name: 'validateUser',
          type: 'function',
          isExported: true,
          signature: 'function validateUser(user: User): boolean',
          dependencies: ['User']
        },
        {
          name: 'INTERNAL_CONFIG',
          type: 'const',
          isExported: false,
          signature: 'const INTERNAL_CONFIG = { ... }',
          dependencies: []
        }
      ],
      children: []
    };

    return structure;
  }

  // 📊 Generate namespace report
  export function generateNamespaceReport(namespaceName: string): {
    structure: NamespaceStructure;
    stats: NamespaceStats;
    recommendations: string[];
    complexity: 'low' | 'medium' | 'high';
  } {
    console.log(`📊 Generating report for namespace: ${namespaceName}`);

    const structure = getNamespaceStructure(namespaceName);
    const stats = analyzeNamespace(namespaceName);
    const recommendations: string[] = [];

    // 🎯 Analyze complexity
    let complexity: 'low' | 'medium' | 'high' = 'low';
    
    if (stats.memberCount > 20) {
      complexity = 'high';
      recommendations.push('Consider splitting large namespace into smaller ones');
    } else if (stats.memberCount > 10) {
      complexity = 'medium';
      recommendations.push('Monitor namespace size for maintainability');
    }

    // 💡 Export recommendations
    const exportRatio = stats.exportedMembers / stats.memberCount;
    if (exportRatio < 0.3) {
      recommendations.push('Low export ratio - consider if all members are needed');
    } else if (exportRatio > 0.8) {
      recommendations.push('High export ratio - ensure internal encapsulation');
    }

    // 🏗️ Structure recommendations
    if (stats.nestedNamespaces === 0 && stats.memberCount > 15) {
      recommendations.push('Consider using nested namespaces for better organization');
    }

    if (stats.interfaces > 10) {
      recommendations.push('Consider creating a dedicated types namespace');
    }

    return {
      structure,
      stats,
      recommendations,
      complexity
    };
  }

  // 🔧 Optimize namespace structure
  export function optimizeNamespaceStructure(
    namespaceName: string
  ): {
    originalStructure: NamespaceStructure;
    optimizedStructure: NamespaceStructure;
    changes: string[];
  } {
    console.log(`🔧 Optimizing namespace structure: ${namespaceName}`);

    const originalStructure = getNamespaceStructure(namespaceName);
    const optimizedStructure = { ...originalStructure };
    const changes: string[] = [];

    // 📂 Group related members
    const groupedMembers = groupMembersByType(originalStructure.members);
    
    // 🏗️ Create nested namespaces for groups
    if (groupedMembers.interfaces.length > 3) {
      optimizedStructure.children.push({
        name: 'Types',
        path: [...originalStructure.path, 'Types'],
        members: groupedMembers.interfaces,
        children: []
      });
      changes.push('Created Types namespace for interfaces');
    }

    if (groupedMembers.functions.length > 5) {
      optimizedStructure.children.push({
        name: 'Utils',
        path: [...originalStructure.path, 'Utils'],
        members: groupedMembers.functions,
        children: []
      });
      changes.push('Created Utils namespace for utility functions');
    }

    // 🧹 Remove grouped members from main namespace
    optimizedStructure.members = originalStructure.members.filter(member =>
      !groupedMembers.interfaces.includes(member) &&
      !groupedMembers.functions.includes(member)
    );

    console.log(`✅ Optimization complete with ${changes.length} changes`);

    return {
      originalStructure,
      optimizedStructure,
      changes
    };
  }

  // 📂 Group members by type
  function groupMembersByType(members: NamespaceMember[]): {
    interfaces: NamespaceMember[];
    classes: NamespaceMember[];
    functions: NamespaceMember[];
    types: NamespaceMember[];
    enums: NamespaceMember[];
    constants: NamespaceMember[];
  } {
    return {
      interfaces: members.filter(m => m.type === 'interface'),
      classes: members.filter(m => m.type === 'class'),
      functions: members.filter(m => m.type === 'function'),
      types: members.filter(m => m.type === 'type'),
      enums: members.filter(m => m.type === 'enum'),
      constants: members.filter(m => m.type === 'const')
    };
  }

  // 📊 Track member usage
  export function trackMemberUsage(memberPath: string): void {
    const currentUsage = memberUsage.get(memberPath) || 0;
    memberUsage.set(memberPath, currentUsage + 1);
  }

  // 🔍 Find unused members
  export function findUnusedMembers(namespaceName: string): NamespaceMember[] {
    const structure = getNamespaceStructure(namespaceName);
    
    return structure.members.filter(member => {
      const memberPath = `${namespaceName}.${member.name}`;
      const usage = memberUsage.get(memberPath) || 0;
      return usage === 0 && member.isExported;
    });
  }

  // 📈 Generate usage statistics
  export function generateUsageStatistics(): {
    totalMembers: number;
    usedMembers: number;
    mostUsedMembers: Array<{ path: string; usage: number }>;
    unusedMembers: string[];
  } {
    const totalMembers = memberUsage.size;
    const usedMembers = Array.from(memberUsage.values()).filter(usage => usage > 0).length;
    
    const sortedUsage = Array.from(memberUsage.entries())
      .sort(([,a], [,b]) => b - a)
      .slice(0, 10);

    const mostUsedMembers = sortedUsage.map(([path, usage]) => ({ path, usage }));
    
    const unusedMembers = Array.from(memberUsage.entries())
      .filter(([, usage]) => usage === 0)
      .map(([path]) => path);

    return {
      totalMembers,
      usedMembers,
      mostUsedMembers,
      unusedMembers
    };
  }
}

// 🎮 Usage examples
const namespaceDemo = (): void => {
  // 🔍 Analyze namespace
  const stats = NamespaceAnalyzer.analyzeNamespace('MyCompany');
  console.log('📊 Namespace Stats:', stats);

  // 📊 Generate comprehensive report
  const report = NamespaceAnalyzer.generateNamespaceReport('MyCompany');
  console.log('📋 Namespace Report:', report);

  // 🔧 Optimize structure
  const optimization = NamespaceAnalyzer.optimizeNamespaceStructure('MyCompany');
  console.log('🔧 Optimization Results:', optimization);

  // 📈 Track usage
  NamespaceAnalyzer.trackMemberUsage('MyCompany.Employee');
  NamespaceAnalyzer.trackMemberUsage('MyCompany.EmployeeManager');
  
  const usageStats = NamespaceAnalyzer.generateUsageStatistics();
  console.log('📈 Usage Statistics:', usageStats);
};

// 🎯 Advanced namespace patterns
namespace AdvancedPatterns {
  // 🌟 Pattern 1: Plugin Architecture
  export namespace PluginSystem {
    export interface Plugin {
      name: string;
      version: string;
      initialize(): void;
      execute(context: PluginContext): PluginResult;
      cleanup(): void;
    }

    export interface PluginContext {
      data: Record<string, any>;
      config: Record<string, any>;
      utilities: PluginUtilities;
    }

    export interface PluginResult {
      success: boolean;
      data?: any;
      errors?: string[];
    }

    export interface PluginUtilities {
      log: (message: string) => void;
      cache: {
        get: (key: string) => any;
        set: (key: string, value: any) => void;
      };
    }

    const registeredPlugins = new Map<string, Plugin>();

    export function registerPlugin(plugin: Plugin): void {
      console.log(`🔌 Registering plugin: ${plugin.name}`);
      registeredPlugins.set(plugin.name, plugin);
      plugin.initialize();
    }

    export function executePlugin(
      pluginName: string, 
      context: PluginContext
    ): PluginResult {
      const plugin = registeredPlugins.get(pluginName);
      if (!plugin) {
        return {
          success: false,
          errors: [`Plugin not found: ${pluginName}`]
        };
      }

      console.log(`⚡ Executing plugin: ${pluginName}`);
      return plugin.execute(context);
    }

    export function listPlugins(): Plugin[] {
      return Array.from(registeredPlugins.values());
    }
  }

  // 🌟 Pattern 2: Event System
  export namespace EventSystem {
    export interface Event<T = any> {
      type: string;
      data: T;
      timestamp: number;
      source?: string;
    }

    export interface EventHandler<T = any> {
      (event: Event<T>): void | Promise<void>;
    }

    export interface EventSubscription {
      unsubscribe(): void;
    }

    const eventListeners = new Map<string, Set<EventHandler>>();
    const eventHistory: Event[] = [];

    export function subscribe<T>(
      eventType: string, 
      handler: EventHandler<T>
    ): EventSubscription {
      console.log(`📡 Subscribing to event: ${eventType}`);
      
      if (!eventListeners.has(eventType)) {
        eventListeners.set(eventType, new Set());
      }
      
      eventListeners.get(eventType)!.add(handler);

      return {
        unsubscribe: () => {
          console.log(`📡 Unsubscribing from event: ${eventType}`);
          eventListeners.get(eventType)?.delete(handler);
        }
      };
    }

    export async function emit<T>(event: Event<T>): Promise<void> {
      console.log(`📢 Emitting event: ${event.type}`);
      
      // 📚 Store in history
      eventHistory.push(event);
      
      // 🔄 Notify all listeners
      const listeners = eventListeners.get(event.type);
      if (listeners) {
        const promises = Array.from(listeners).map(handler => 
          Promise.resolve(handler(event))
        );
        await Promise.all(promises);
      }
    }

    export function createEvent<T>(
      type: string, 
      data: T, 
      source?: string
    ): Event<T> {
      return {
        type,
        data,
        timestamp: Date.now(),
        source
      };
    }

    export function getEventHistory(
      eventType?: string,
      limit?: number
    ): Event[] {
      let events = eventHistory;
      
      if (eventType) {
        events = events.filter(event => event.type === eventType);
      }
      
      if (limit) {
        events = events.slice(-limit);
      }
      
      return events;
    }
  }

  // 🌟 Pattern 3: State Management
  export namespace StateManager {
    export interface State {
      [key: string]: any;
    }

    export interface StateChange<T = any> {
      path: string;
      oldValue: T;
      newValue: T;
      timestamp: number;
    }

    export interface StateSubscriber {
      (change: StateChange): void;
    }

    let currentState: State = {};
    const subscribers = new Set<StateSubscriber>();
    const stateHistory: StateChange[] = [];

    export function getState(): State {
      return { ...currentState };
    }

    export function setState(path: string, value: any): void {
      const oldValue = getValueAtPath(currentState, path);
      
      if (oldValue !== value) {
        console.log(`🔄 State change: ${path}`);
        
        setValueAtPath(currentState, path, value);
        
        const change: StateChange = {
          path,
          oldValue,
          newValue: value,
          timestamp: Date.now()
        };

        stateHistory.push(change);
        notifySubscribers(change);
      }
    }

    export function subscribe(subscriber: StateSubscriber): () => void {
      console.log(`📡 Subscribing to state changes`);
      subscribers.add(subscriber);
      
      return () => {
        console.log(`📡 Unsubscribing from state changes`);
        subscribers.delete(subscriber);
      };
    }

    export function getStateHistory(path?: string): StateChange[] {
      if (path) {
        return stateHistory.filter(change => change.path === path);
      }
      return [...stateHistory];
    }

    function getValueAtPath(obj: any, path: string): any {
      return path.split('.').reduce((current, key) => current?.[key], obj);
    }

    function setValueAtPath(obj: any, path: string, value: any): void {
      const keys = path.split('.');
      const lastKey = keys.pop()!;
      const target = keys.reduce((current, key) => {
        if (!(key in current)) {
          current[key] = {};
        }
        return current[key];
      }, obj);
      
      target[lastKey] = value;
    }

    function notifySubscribers(change: StateChange): void {
      subscribers.forEach(subscriber => {
        try {
          subscriber(change);
        } catch (error) {
          console.error('State subscriber error:', error);
        }
      });
    }
  }

  // 🌟 Pattern 4: Configuration Management
  export namespace ConfigManager {
    export interface ConfigSchema {
      [key: string]: {
        type: 'string' | 'number' | 'boolean' | 'object' | 'array';
        required?: boolean;
        default?: any;
        validator?: (value: any) => boolean;
        description?: string;
      };
    }

    export interface ConfigValue {
      value: any;
      source: 'default' | 'environment' | 'file' | 'runtime';
      validated: boolean;
    }

    const configSchemas = new Map<string, ConfigSchema>();
    const configValues = new Map<string, ConfigValue>();

    export function defineSchema(name: string, schema: ConfigSchema): void {
      console.log(`📋 Defining config schema: ${name}`);
      configSchemas.set(name, schema);
      
      // 🎯 Apply default values
      Object.entries(schema).forEach(([key, config]) => {
        if (config.default !== undefined) {
          setConfig(`${name}.${key}`, config.default, 'default');
        }
      });
    }

    export function setConfig(
      path: string, 
      value: any, 
      source: ConfigValue['source'] = 'runtime'
    ): boolean {
      console.log(`⚙️ Setting config: ${path} = ${value}`);
      
      const isValid = validateConfig(path, value);
      
      configValues.set(path, {
        value,
        source,
        validated: isValid
      });

      return isValid;
    }

    export function getConfig<T = any>(path: string): T | undefined {
      const configValue = configValues.get(path);
      return configValue?.value;
    }

    export function validateConfig(path: string, value: any): boolean {
      const [schemaName, configKey] = path.split('.');
      const schema = configSchemas.get(schemaName);
      
      if (!schema || !schema[configKey]) {
        return false;
      }

      const config = schema[configKey];
      
      // 🎯 Type validation
      if (!validateType(value, config.type)) {
        return false;
      }

      // 🔧 Custom validation
      if (config.validator && !config.validator(value)) {
        return false;
      }

      return true;
    }

    function validateType(value: any, expectedType: string): boolean {
      switch (expectedType) {
        case 'string':
          return typeof value === 'string';
        case 'number':
          return typeof value === 'number' && !isNaN(value);
        case 'boolean':
          return typeof value === 'boolean';
        case 'object':
          return typeof value === 'object' && value !== null && !Array.isArray(value);
        case 'array':
          return Array.isArray(value);
        default:
          return false;
      }
    }

    export function getAllConfigs(): Record<string, ConfigValue> {
      return Object.fromEntries(configValues);
    }

    export function validateAllConfigs(): {
      valid: string[];
      invalid: string[];
    } {
      const valid: string[] = [];
      const invalid: string[] = [];

      configValues.forEach((configValue, path) => {
        if (configValue.validated) {
          valid.push(path);
        } else {
          invalid.push(path);
        }
      });

      return { valid, invalid };
    }
  }
}

// 🎮 Advanced usage examples
const advancedNamespaceDemo = (): void => {
  // 🔌 Plugin system demo
  const examplePlugin: AdvancedPatterns.PluginSystem.Plugin = {
    name: 'ExamplePlugin',
    version: '1.0.0',
    initialize: () => console.log('🔌 Plugin initialized'),
    execute: (context) => {
      console.log('⚡ Plugin executing with context:', context.data);
      return { success: true, data: 'Plugin result' };
    },
    cleanup: () => console.log('🧹 Plugin cleaned up')
  };

  AdvancedPatterns.PluginSystem.registerPlugin(examplePlugin);

  const pluginResult = AdvancedPatterns.PluginSystem.executePlugin('ExamplePlugin', {
    data: { input: 'test' },
    config: {},
    utilities: {
      log: console.log,
      cache: {
        get: (key) => `cached_${key}`,
        set: (key, value) => console.log(`Cache set: ${key} = ${value}`)
      }
    }
  });

  // 📡 Event system demo
  const subscription = AdvancedPatterns.EventSystem.subscribe('user.login', (event) => {
    console.log(`👤 User logged in:`, event.data);
  });

  AdvancedPatterns.EventSystem.emit(
    AdvancedPatterns.EventSystem.createEvent('user.login', { userId: '123', name: 'John' })
  );

  // 🔄 State management demo
  const stateUnsubscribe = AdvancedPatterns.StateManager.subscribe((change) => {
    console.log(`📊 State changed:`, change);
  });

  AdvancedPatterns.StateManager.setState('user.name', 'Alice');
  AdvancedPatterns.StateManager.setState('app.theme', 'dark');

  // ⚙️ Configuration demo
  AdvancedPatterns.ConfigManager.defineSchema('app', {
    apiUrl: {
      type: 'string',
      required: true,
      description: 'API base URL'
    },
    timeout: {
      type: 'number',
      default: 5000,
      validator: (value) => value > 0,
      description: 'Request timeout in milliseconds'
    },
    debug: {
      type: 'boolean',
      default: false,
      description: 'Enable debug mode'
    }
  });

  AdvancedPatterns.ConfigManager.setConfig('app.apiUrl', 'https://api.example.com');
  AdvancedPatterns.ConfigManager.setConfig('app.debug', true);

  const apiUrl = AdvancedPatterns.ConfigManager.getConfig<string>('app.apiUrl');
  console.log('🔧 API URL:', apiUrl);
};

// 🎯 Execute demonstrations
namespaceDemo();
advancedNamespaceDemo();

💡 Common Namespace Patterns

Let’s explore the most effective patterns for organizing code with namespaces:

// 🌟 Pattern 1: Domain-Driven Organization
// Organize namespaces around business domains

namespace ECommerce {
  // 🛍️ Product domain
  export namespace Products {
    export interface Product {
      id: string;
      name: string;
      price: number;
      category: Category;
      inventory: InventoryInfo;
    }

    export interface Category {
      id: string;
      name: string;
      parent?: Category;
    }

    export interface InventoryInfo {
      inStock: number;
      reserved: number;
      available: number;
    }

    export class ProductService {
      async getProduct(id: string): Promise<Product | null> {
        // Implementation
        return null;
      }

      async updateInventory(
        productId: string, 
        quantity: number
      ): Promise<void> {
        // Implementation
      }
    }

    export namespace Validators {
      export function validateProduct(product: Product): boolean {
        return product.id.length > 0 && 
               product.price > 0 && 
               product.inventory.available >= 0;
      }

      export function validateCategory(category: Category): boolean {
        return category.id.length > 0 && category.name.length > 0;
      }
    }
  }

  // 👤 User domain
  export namespace Users {
    export interface User {
      id: string;
      email: string;
      profile: UserProfile;
      preferences: UserPreferences;
    }

    export interface UserProfile {
      firstName: string;
      lastName: string;
      avatar?: string;
      addresses: Address[];
    }

    export interface Address {
      id: string;
      street: string;
      city: string;
      postalCode: string;
      country: string;
      isDefault: boolean;
    }

    export interface UserPreferences {
      currency: string;
      language: string;
      emailNotifications: boolean;
      smsNotifications: boolean;
    }

    export class UserService {
      async createUser(userData: CreateUserData): Promise<User> {
        // Implementation
        return {} as User;
      }

      async updateProfile(
        userId: string, 
        profile: Partial<UserProfile>
      ): Promise<void> {
        // Implementation
      }
    }

    export type CreateUserData = Omit<User, 'id'>;
  }

  // 🛒 Order domain
  export namespace Orders {
    export interface Order {
      id: string;
      userId: string;
      items: OrderItem[];
      shipping: ShippingInfo;
      payment: PaymentInfo;
      status: OrderStatus;
      totals: OrderTotals;
    }

    export interface OrderItem {
      productId: string;
      quantity: number;
      unitPrice: number;
      totalPrice: number;
    }

    export interface ShippingInfo {
      address: Users.Address;
      method: ShippingMethod;
      trackingNumber?: string;
    }

    export interface PaymentInfo {
      method: PaymentMethod;
      transactionId: string;
      amount: number;
    }

    export type OrderStatus = 
      | 'pending' 
      | 'confirmed' 
      | 'processing' 
      | 'shipped' 
      | 'delivered' 
      | 'cancelled';

    export type ShippingMethod = 'standard' | 'express' | 'overnight';
    export type PaymentMethod = 'credit_card' | 'paypal' | 'bank_transfer';

    export interface OrderTotals {
      subtotal: number;
      tax: number;
      shipping: number;
      discount: number;
      total: number;
    }

    export class OrderService {
      async createOrder(orderData: CreateOrderData): Promise<Order> {
        // Implementation
        return {} as Order;
      }

      async updateOrderStatus(
        orderId: string, 
        status: OrderStatus
      ): Promise<void> {
        // Implementation
      }
    }

    export type CreateOrderData = Omit<Order, 'id' | 'status'>;
  }

  // 💳 Payment domain
  export namespace Payments {
    export interface PaymentProcessor {
      processPayment(request: PaymentRequest): Promise<PaymentResult>;
      refundPayment(transactionId: string, amount: number): Promise<RefundResult>;
    }

    export interface PaymentRequest {
      amount: number;
      currency: string;
      method: Orders.PaymentMethod;
      customerInfo: PaymentCustomerInfo;
      metadata?: Record<string, any>;
    }

    export interface PaymentCustomerInfo {
      id: string;
      email: string;
      name: string;
    }

    export interface PaymentResult {
      success: boolean;
      transactionId: string;
      amount: number;
      fees: number;
      error?: PaymentError;
    }

    export interface RefundResult {
      success: boolean;
      refundId: string;
      amount: number;
      error?: PaymentError;
    }

    export interface PaymentError {
      code: string;
      message: string;
      details?: Record<string, any>;
    }

    export class StripePaymentProcessor implements PaymentProcessor {
      async processPayment(request: PaymentRequest): Promise<PaymentResult> {
        // Stripe implementation
        return {} as PaymentResult;
      }

      async refundPayment(
        transactionId: string, 
        amount: number
      ): Promise<RefundResult> {
        // Stripe refund implementation
        return {} as RefundResult;
      }
    }
  }
}

// 🌟 Pattern 2: Technical Layer Organization
// Organize by technical concerns and layers

namespace Application {
  // 🗄️ Data layer
  export namespace Data {
    export interface Repository<T, K = string> {
      findById(id: K): Promise<T | null>;
      findAll(): Promise<T[]>;
      create(entity: Omit<T, 'id'>): Promise<T>;
      update(id: K, entity: Partial<T>): Promise<T>;
      delete(id: K): Promise<void>;
    }

    export interface QueryBuilder<T> {
      where(field: keyof T, value: any): QueryBuilder<T>;
      orderBy(field: keyof T, direction: 'asc' | 'desc'): QueryBuilder<T>;
      limit(count: number): QueryBuilder<T>;
      offset(count: number): QueryBuilder<T>;
      execute(): Promise<T[]>;
    }

    export class DatabaseConnection {
      private isConnected = false;

      async connect(connectionString: string): Promise<void> {
        console.log('🔌 Connecting to database...');
        this.isConnected = true;
      }

      async disconnect(): Promise<void> {
        console.log('🔌 Disconnecting from database...');
        this.isConnected = false;
      }

      isHealthy(): boolean {
        return this.isConnected;
      }
    }

    export abstract class BaseRepository<T, K = string> implements Repository<T, K> {
      protected abstract tableName: string;

      async findById(id: K): Promise<T | null> {
        console.log(`🔍 Finding ${this.tableName} by ID: ${id}`);
        // Implementation
        return null;
      }

      async findAll(): Promise<T[]> {
        console.log(`📋 Finding all ${this.tableName}`);
        // Implementation
        return [];
      }

      async create(entity: Omit<T, 'id'>): Promise<T> {
        console.log(`➕ Creating ${this.tableName}`);
        // Implementation
        return entity as T;
      }

      async update(id: K, entity: Partial<T>): Promise<T> {
        console.log(`✏️ Updating ${this.tableName} ${id}`);
        // Implementation
        return entity as T;
      }

      async delete(id: K): Promise<void> {
        console.log(`🗑️ Deleting ${this.tableName} ${id}`);
        // Implementation
      }
    }
  }

  // 🏗️ Service layer
  export namespace Services {
    export interface ServiceContext {
      userId?: string;
      requestId: string;
      timestamp: number;
      metadata: Record<string, any>;
    }

    export interface ServiceResult<T> {
      success: boolean;
      data?: T;
      error?: ServiceError;
    }

    export interface ServiceError {
      code: string;
      message: string;
      details?: any;
    }

    export abstract class BaseService {
      protected context?: ServiceContext;

      setContext(context: ServiceContext): void {
        this.context = context;
      }

      protected createResult<T>(data: T): ServiceResult<T> {
        return { success: true, data };
      }

      protected createError(
        code: string, 
        message: string, 
        details?: any
      ): ServiceResult<never> {
        return {
          success: false,
          error: { code, message, details }
        };
      }

      protected logOperation(operation: string, details?: any): void {
        console.log(`🔧 Service operation: ${operation}`, {
          service: this.constructor.name,
          context: this.context?.requestId,
          details
        });
      }
    }

    export class ValidationService extends BaseService {
      validate<T>(data: T, rules: ValidationRules<T>): ServiceResult<T> {
        this.logOperation('validate', { rules });

        for (const [field, rule] of Object.entries(rules)) {
          const value = (data as any)[field];
          
          if (!this.validateField(value, rule as ValidationRule)) {
            return this.createError(
              'VALIDATION_FAILED',
              `Validation failed for field: ${field}`
            );
          }
        }

        return this.createResult(data);
      }

      private validateField(value: any, rule: ValidationRule): boolean {
        if (rule.required && (value === undefined || value === null)) {
          return false;
        }

        if (rule.type && typeof value !== rule.type) {
          return false;
        }

        if (rule.validator && !rule.validator(value)) {
          return false;
        }

        return true;
      }
    }

    export interface ValidationRule {
      required?: boolean;
      type?: string;
      validator?: (value: any) => boolean;
    }

    export type ValidationRules<T> = {
      [K in keyof T]?: ValidationRule;
    };
  }

  // 🌐 Web layer
  export namespace Web {
    export interface Request {
      method: string;
      url: string;
      headers: Record<string, string>;
      body?: any;
      params: Record<string, string>;
      query: Record<string, string>;
    }

    export interface Response {
      status: number;
      headers: Record<string, string>;
      body?: any;
    }

    export interface Middleware {
      (request: Request, response: Response, next: () => void): void | Promise<void>;
    }

    export interface Controller {
      handle(request: Request): Promise<Response>;
    }

    export abstract class BaseController implements Controller {
      abstract handle(request: Request): Promise<Response>;

      protected createResponse(
        status: number, 
        body?: any, 
        headers?: Record<string, string>
      ): Response {
        return {
          status,
          body,
          headers: headers || {}
        };
      }

      protected ok(data?: any): Response {
        return this.createResponse(200, data);
      }

      protected created(data?: any): Response {
        return this.createResponse(201, data);
      }

      protected badRequest(error?: string): Response {
        return this.createResponse(400, { error });
      }

      protected notFound(error?: string): Response {
        return this.createResponse(404, { error });
      }

      protected serverError(error?: string): Response {
        return this.createResponse(500, { error });
      }
    }

    export class Router {
      private routes = new Map<string, Controller>();

      register(path: string, controller: Controller): void {
        console.log(`🛣️ Registering route: ${path}`);
        this.routes.set(path, controller);
      }

      async route(request: Request): Promise<Response> {
        const controller = this.routes.get(request.url);
        
        if (!controller) {
          return {
            status: 404,
            headers: {},
            body: { error: 'Route not found' }
          };
        }

        return await controller.handle(request);
      }
    }
  }

  // 🔧 Utilities layer
  export namespace Utils {
    export namespace Logger {
      export enum LogLevel {
        DEBUG = 0,
        INFO = 1,
        WARN = 2,
        ERROR = 3
      }

      export interface LogEntry {
        level: LogLevel;
        message: string;
        timestamp: number;
        context?: any;
      }

      let currentLogLevel = LogLevel.INFO;

      export function setLogLevel(level: LogLevel): void {
        currentLogLevel = level;
      }

      export function debug(message: string, context?: any): void {
        log(LogLevel.DEBUG, message, context);
      }

      export function info(message: string, context?: any): void {
        log(LogLevel.INFO, message, context);
      }

      export function warn(message: string, context?: any): void {
        log(LogLevel.WARN, message, context);
      }

      export function error(message: string, context?: any): void {
        log(LogLevel.ERROR, message, context);
      }

      function log(level: LogLevel, message: string, context?: any): void {
        if (level >= currentLogLevel) {
          const entry: LogEntry = {
            level,
            message,
            timestamp: Date.now(),
            context
          };

          console.log(`[${LogLevel[level]}] ${message}`, context || '');
        }
      }
    }

    export namespace Cache {
      const cache = new Map<string, CacheEntry>();

      interface CacheEntry {
        value: any;
        expiry: number;
      }

      export function set(
        key: string, 
        value: any, 
        ttlSeconds: number = 300
      ): void {
        const expiry = Date.now() + (ttlSeconds * 1000);
        cache.set(key, { value, expiry });
      }

      export function get<T = any>(key: string): T | null {
        const entry = cache.get(key);
        
        if (!entry) {
          return null;
        }

        if (Date.now() > entry.expiry) {
          cache.delete(key);
          return null;
        }

        return entry.value;
      }

      export function has(key: string): boolean {
        return get(key) !== null;
      }

      export function delete(key: string): boolean {
        return cache.delete(key);
      }

      export function clear(): void {
        cache.clear();
      }

      export function size(): number {
        // Clean expired entries first
        const now = Date.now();
        for (const [key, entry] of cache.entries()) {
          if (now > entry.expiry) {
            cache.delete(key);
          }
        }
        return cache.size;
      }
    }

    export namespace Crypto {
      export function generateId(length: number = 8): string {
        const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
        let result = '';
        
        for (let i = 0; i < length; i++) {
          result += chars.charAt(Math.floor(Math.random() * chars.length));
        }
        
        return result;
      }

      export function hash(input: string): string {
        // Simple hash function (use proper crypto in production)
        let hash = 0;
        
        for (let i = 0; i < input.length; i++) {
          const char = input.charCodeAt(i);
          hash = ((hash << 5) - hash) + char;
          hash = hash & hash; // Convert to 32-bit integer
        }
        
        return Math.abs(hash).toString(16);
      }
    }
  }
}

// Usage examples demonstrating the organized structure
const layeredArchitectureDemo = (): void => {
  // 🗄️ Data layer usage
  class UserRepository extends Application.Data.BaseRepository<ECommerce.Users.User> {
    protected tableName = 'users';
  }

  // 🏗️ Service layer usage
  class UserService extends Application.Services.BaseService {
    constructor(private userRepo: UserRepository) {
      super();
    }

    async createUser(userData: ECommerce.Users.CreateUserData): Promise<Application.Services.ServiceResult<ECommerce.Users.User>> {
      this.logOperation('createUser');
      
      try {
        const user = await this.userRepo.create(userData);
        return this.createResult(user);
      } catch (error) {
        return this.createError('USER_CREATION_FAILED', 'Failed to create user');
      }
    }
  }

  // 🌐 Web layer usage
  class UserController extends Application.Web.BaseController {
    constructor(private userService: UserService) {
      super();
    }

    async handle(request: Application.Web.Request): Promise<Application.Web.Response> {
      if (request.method === 'POST') {
        const result = await this.userService.createUser(request.body);
        
        if (result.success) {
          return this.created(result.data);
        } else {
          return this.badRequest(result.error?.message);
        }
      }

      return this.badRequest('Method not allowed');
    }
  }

  // 🔧 Utilities usage
  Application.Utils.Logger.setLogLevel(Application.Utils.Logger.LogLevel.DEBUG);
  Application.Utils.Logger.info('Application starting...');
  
  Application.Utils.Cache.set('user:123', { name: 'John' }, 60);
  const cachedUser = Application.Utils.Cache.get('user:123');
  
  const sessionId = Application.Utils.Crypto.generateId(16);
  console.log('Generated session ID:', sessionId);
};

// Execute the demo
layeredArchitectureDemo();

🎉 Conclusion

Congratulations! You’ve mastered the fundamentals of TypeScript namespaces! 🏢

🎯 What You’ve Learned

  • 🏗️ Namespace Syntax: Creating and organizing code with namespace declarations
  • 📂 Hierarchical Organization: Building logical code structures with nested namespaces
  • 🔧 Advanced Patterns: Sophisticated namespace patterns for different architectural needs
  • 📊 Code Analysis: Tools and techniques for analyzing and optimizing namespace structures
  • 🎯 Best Practices: Effective strategies for maintaining organized, scalable codebases

🚀 Key Benefits

  • 🏗️ Better Organization: Clear, logical structure for large codebases
  • 🔒 Encapsulation: Control over what gets exposed publicly vs. kept internal
  • 📂 Hierarchical Structure: Natural grouping of related functionality
  • 🚫 Naming Conflict Prevention: Isolated scope prevents name collisions
  • 📚 Self-Documenting Code: Structure that clearly communicates intent and relationships

🔥 Best Practices Recap

  1. 🎯 Group by Purpose: Organize related functionality together logically
  2. 🔒 Control Exports: Only export what should be part of the public API
  3. 📂 Use Hierarchies: Leverage nested namespaces for complex domains
  4. 📊 Monitor Complexity: Keep individual namespaces focused and manageable
  5. 🔧 Consider Modern Alternatives: Evaluate when ES6 modules might be more appropriate

You’re now equipped to create well-organized, maintainable TypeScript codebases using namespaces effectively! Whether you’re building libraries, organizing large applications, or creating domain-specific APIs, namespaces provide powerful tools for code organization. 🌟

Happy coding, and may your code always be beautifully organized! 🏢✨