+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Part 139 of 355

πŸ”€ Declaration Merging: Combining Declarations

Master declaration merging to combine multiple declarations into single entities, extend libraries safely, and create flexible type definitions πŸš€

πŸ’ŽAdvanced
26 min read

Prerequisites

  • Understanding of TypeScript interfaces and namespaces πŸ“
  • Knowledge of module systems and type declarations ⚑
  • Familiarity with TypeScript compilation process πŸ’»

What you'll learn

  • Master all types of declaration merging patterns 🎯
  • Safely extend existing types and library definitions πŸ—οΈ
  • Create flexible and maintainable type architectures πŸ›
  • Build sophisticated declaration merging systems ✨

🎯 Introduction

Welcome to the magical world of TypeScript’s declaration merging! πŸ”€ If TypeScript declarations were like LEGO blocks, then declaration merging is like having the superpower to combine identical blocks automatically - when you have multiple interface declarations with the same name, TypeScript doesn’t throw an error; instead, it intelligently merges them into one super-interface with all the properties and methods from each declaration!

Declaration merging is one of TypeScript’s most powerful and flexible features, allowing you to extend existing types, patch library definitions, create modular type architectures, and build sophisticated type systems that can grow and evolve over time. It’s particularly valuable when working with third-party libraries, creating extensible APIs, and building large-scale applications.

By the end of this tutorial, you’ll be a declaration merging expert, capable of leveraging this powerful feature to create flexible, maintainable, and extensible type systems that can adapt to any requirement. Let’s master the art of declaration fusion! 🌟

πŸ“š Understanding Declaration Merging

πŸ€” What Is Declaration Merging?

Declaration merging is TypeScript’s process of combining multiple declarations with the same name into a single definition. This allows you to extend types across multiple files, add functionality to existing libraries, and create modular type definitions that can be combined in flexible ways.

// 🌟 Basic interface merging examples

// First interface declaration
interface User {
  id: string;
  name: string;
}

// Second interface declaration with the same name
interface User {
  email: string;
  createdAt: Date;
}

// Third interface declaration adding more properties
interface User {
  profile: UserProfile;
  preferences: UserPreferences;
}

// TypeScript automatically merges all declarations into one
// The final User interface contains all properties:
// {
//   id: string;
//   name: string;
//   email: string;
//   createdAt: Date;
//   profile: UserProfile;
//   preferences: UserPreferences;
// }

interface UserProfile {
  avatar: string;
  bio: string;
  location: string;
  website?: string;
}

interface UserPreferences {
  theme: 'light' | 'dark';
  language: string;
  notifications: NotificationSettings;
  privacy: PrivacySettings;
}

interface NotificationSettings {
  email: boolean;
  push: boolean;
  sms: boolean;
  digest: 'daily' | 'weekly' | 'monthly' | 'never';
}

interface PrivacySettings {
  profileVisibility: 'public' | 'private' | 'friends';
  searchable: boolean;
  showOnlineStatus: boolean;
  allowDirectMessages: boolean;
}

// ✨ Using the merged interface
const createUser = (userData: Partial<User>): User => {
  return {
    id: generateId(),
    name: userData.name || 'Anonymous',
    email: userData.email || '',
    createdAt: new Date(),
    profile: userData.profile || {
      avatar: '',
      bio: '',
      location: ''
    },
    preferences: userData.preferences || {
      theme: 'light',
      language: 'en',
      notifications: {
        email: true,
        push: true,
        sms: false,
        digest: 'weekly'
      },
      privacy: {
        profileVisibility: 'public',
        searchable: true,
        showOnlineStatus: true,
        allowDirectMessages: true
      }
    }
  };
};

// 🎯 Namespace merging
namespace DatabaseOperations {
  export interface Connection {
    host: string;
    port: number;
    database: string;
  }
  
  export function connect(config: Connection): Promise<void> {
    return Promise.resolve();
  }
}

// Extending the namespace with additional functionality
namespace DatabaseOperations {
  export interface QueryOptions {
    limit?: number;
    offset?: number;
    sort?: string;
    filter?: Record<string, any>;
  }
  
  export function query<T>(sql: string, options?: QueryOptions): Promise<T[]> {
    return Promise.resolve([]);
  }
}

// Adding more operations to the namespace
namespace DatabaseOperations {
  export interface TransactionOptions {
    isolation?: 'read_uncommitted' | 'read_committed' | 'repeatable_read' | 'serializable';
    timeout?: number;
    readonly?: boolean;
  }
  
  export function transaction<T>(
    callback: (tx: Transaction) => Promise<T>,
    options?: TransactionOptions
  ): Promise<T> {
    // Transaction implementation
    return Promise.resolve({} as T);
  }
  
  export interface Transaction {
    query<T>(sql: string, params?: any[]): Promise<T[]>;
    commit(): Promise<void>;
    rollback(): Promise<void>;
  }
}

// The merged namespace contains all declarations
const dbExample = async () => {
  await DatabaseOperations.connect({
    host: 'localhost',
    port: 5432,
    database: 'myapp'
  });
  
  const users = await DatabaseOperations.query<User>('SELECT * FROM users', {
    limit: 10,
    sort: 'created_at DESC'
  });
  
  await DatabaseOperations.transaction(async (tx) => {
    await tx.query('INSERT INTO logs VALUES (?)', ['User accessed']);
    await tx.commit();
  });
};

function generateId(): string {
  return Math.random().toString(36).substr(2, 9);
}

πŸ—οΈ Advanced Declaration Merging Patterns

// πŸš€ Function and namespace merging

// Function declaration
function APIClient(baseUrl: string): APIClient.Instance {
  return new APIClient.ClientImpl(baseUrl);
}

// Namespace with the same name (merges with function)
namespace APIClient {
  export interface Instance {
    get<T>(path: string, config?: RequestConfig): Promise<APIResponse<T>>;
    post<T>(path: string, data?: any, config?: RequestConfig): Promise<APIResponse<T>>;
    put<T>(path: string, data?: any, config?: RequestConfig): Promise<APIResponse<T>>;
    delete<T>(path: string, config?: RequestConfig): Promise<APIResponse<T>>;
    
    // Advanced methods
    upload<T>(path: string, file: File, config?: UploadConfig): Promise<APIResponse<T>>;
    download(path: string, config?: DownloadConfig): Promise<Blob>;
    batch<T>(requests: BatchRequest[]): Promise<BatchResponse<T>>;
  }
  
  export interface RequestConfig {
    headers?: Record<string, string>;
    timeout?: number;
    retries?: number;
    cache?: boolean;
    validateStatus?: (status: number) => boolean;
  }
  
  export interface UploadConfig extends RequestConfig {
    onProgress?: (progress: number) => void;
    chunkSize?: number;
  }
  
  export interface DownloadConfig extends RequestConfig {
    onProgress?: (progress: number) => void;
    responseType?: 'blob' | 'arraybuffer' | 'stream';
  }
  
  export interface APIResponse<T> {
    data: T;
    status: number;
    statusText: string;
    headers: Record<string, string>;
    config: RequestConfig;
    timing: ResponseTiming;
  }
  
  export interface ResponseTiming {
    start: number;
    end: number;
    duration: number;
    dnsLookup?: number;
    tcpConnection?: number;
    tlsHandshake?: number;
    firstByte?: number;
    download?: number;
  }
  
  export interface BatchRequest {
    method: 'GET' | 'POST' | 'PUT' | 'DELETE';
    path: string;
    data?: any;
    config?: RequestConfig;
    id?: string;
  }
  
  export interface BatchResponse<T> {
    results: Array<{
      id?: string;
      success: boolean;
      data?: T;
      error?: APIError;
      status: number;
    }>;
    timing: ResponseTiming;
  }
  
  export interface APIError {
    code: string;
    message: string;
    details?: any;
    timestamp: Date;
    requestId?: string;
  }
  
  // Implementation class
  export class ClientImpl implements Instance {
    constructor(private baseUrl: string) {}
    
    async get<T>(path: string, config?: RequestConfig): Promise<APIResponse<T>> {
      return this.request<T>('GET', path, undefined, config);
    }
    
    async post<T>(path: string, data?: any, config?: RequestConfig): Promise<APIResponse<T>> {
      return this.request<T>('POST', path, data, config);
    }
    
    async put<T>(path: string, data?: any, config?: RequestConfig): Promise<APIResponse<T>> {
      return this.request<T>('PUT', path, data, config);
    }
    
    async delete<T>(path: string, config?: RequestConfig): Promise<APIResponse<T>> {
      return this.request<T>('DELETE', path, undefined, config);
    }
    
    async upload<T>(path: string, file: File, config?: UploadConfig): Promise<APIResponse<T>> {
      // Upload implementation with progress tracking
      return this.request<T>('POST', path, file, config);
    }
    
    async download(path: string, config?: DownloadConfig): Promise<Blob> {
      // Download implementation
      const response = await this.request<ArrayBuffer>('GET', path, undefined, config);
      return new Blob([response.data]);
    }
    
    async batch<T>(requests: BatchRequest[]): Promise<BatchResponse<T>> {
      // Batch request implementation
      const results = await Promise.allSettled(
        requests.map(req => this.request<T>(req.method, req.path, req.data, req.config))
      );
      
      return {
        results: results.map((result, index) => ({
          id: requests[index].id,
          success: result.status === 'fulfilled',
          data: result.status === 'fulfilled' ? result.value.data : undefined,
          error: result.status === 'rejected' ? result.reason : undefined,
          status: result.status === 'fulfilled' ? result.value.status : 500
        })),
        timing: {
          start: Date.now(),
          end: Date.now(),
          duration: 0
        }
      };
    }
    
    private async request<T>(
      method: string, 
      path: string, 
      data?: any, 
      config?: RequestConfig
    ): Promise<APIResponse<T>> {
      const start = Date.now();
      
      // Request implementation
      const response = {
        data: {} as T,
        status: 200,
        statusText: 'OK',
        headers: {},
        config: config || {},
        timing: {
          start,
          end: Date.now(),
          duration: Date.now() - start
        }
      };
      
      return response;
    }
  }
  
  // Static methods and properties
  export const version = '1.0.0';
  export const defaults: RequestConfig = {
    timeout: 30000,
    retries: 3,
    cache: true,
    validateStatus: (status) => status >= 200 && status < 300
  };
  
  export function createInstance(baseUrl: string, config?: RequestConfig): Instance {
    const instance = new ClientImpl(baseUrl);
    // Apply default config
    return instance;
  }
}

// Now APIClient is both a function and a namespace
const client = APIClient('https://api.example.com');
const customClient = APIClient.createInstance('https://api.example.com', {
  timeout: 60000,
  headers: { 'Authorization': 'Bearer token' }
});

// πŸ”§ Class and namespace merging
class Logger {
  constructor(private name: string) {}
  
  log(message: string): void {
    console.log(`[${this.name}] ${message}`);
  }
  
  error(message: string, error?: Error): void {
    console.error(`[${this.name}] ERROR: ${message}`, error);
  }
}

namespace Logger {
  export type LogLevel = 'debug' | 'info' | 'warn' | 'error';
  
  export interface LogEntry {
    timestamp: Date;
    level: LogLevel;
    message: string;
    metadata?: Record<string, any>;
    source: string;
  }
  
  export interface LoggerConfig {
    level: LogLevel;
    format: 'json' | 'text';
    output: 'console' | 'file' | 'remote';
    filters?: LogFilter[];
  }
  
  export interface LogFilter {
    level?: LogLevel;
    source?: string;
    pattern?: RegExp;
    exclude?: boolean;
  }
  
  // Static factory methods
  export function create(name: string, config?: LoggerConfig): Logger {
    const logger = new Logger(name);
    // Apply configuration
    return logger;
  }
  
  export function getLogger(name: string): Logger {
    return loggerInstances.get(name) || create(name);
  }
  
  // Global logger registry
  const loggerInstances = new Map<string, Logger>();
  
  export function configure(config: LoggerConfig): void {
    globalConfig = { ...globalConfig, ...config };
  }
  
  export function setGlobalLevel(level: LogLevel): void {
    globalConfig.level = level;
  }
  
  let globalConfig: LoggerConfig = {
    level: 'info',
    format: 'text',
    output: 'console'
  };
}

// Usage of merged class and namespace
const appLogger = Logger.create('App', {
  level: 'debug',
  format: 'json',
  output: 'file'
});

Logger.setGlobalLevel('warn');
const serviceLogger = Logger.getLogger('Service');

πŸ› οΈ Building a Declaration Merging Management System

Let’s create a comprehensive system for managing and tracking declaration merging:

// πŸ—οΈ Declaration Merging Analysis and Management System

namespace DeclarationMerging {
  
  // πŸ“‹ Core interfaces for tracking merging
  export interface MergeRegistry {
    declarations: Map<string, DeclarationInfo[]>;
    mergedTypes: Map<string, MergedTypeInfo>;
    conflicts: MergeConflict[];
    metrics: MergeMetrics;
  }
  
  export interface DeclarationInfo {
    name: string;
    type: DeclarationType;
    source: SourceLocation;
    properties: PropertyInfo[];
    methods: MethodInfo[];
    callSignatures: CallSignatureInfo[];
    constructSignatures: ConstructSignatureInfo[];
    indexSignatures: IndexSignatureInfo[];
    generics: GenericInfo[];
    extends: string[];
    implements: string[];
    accessibility: 'public' | 'private' | 'protected';
    namespace?: string;
    module?: string;
    exported: boolean;
    ambient: boolean;
    createdAt: Date;
  }
  
  export type DeclarationType = 
    | 'interface' 
    | 'namespace' 
    | 'class' 
    | 'function' 
    | 'variable' 
    | 'type' 
    | 'enum' 
    | 'module';
  
  export interface SourceLocation {
    file: string;
    line: number;
    column: number;
    length: number;
  }
  
  export interface PropertyInfo {
    name: string;
    type: string;
    optional: boolean;
    readonly: boolean;
    static: boolean;
    accessibility: 'public' | 'private' | 'protected';
    decorators: string[];
    documentation?: string;
  }
  
  export interface MethodInfo {
    name: string;
    signature: string;
    returnType: string;
    parameters: ParameterInfo[];
    overloads: MethodOverload[];
    static: boolean;
    abstract: boolean;
    accessibility: 'public' | 'private' | 'protected';
    decorators: string[];
    documentation?: string;
  }
  
  export interface ParameterInfo {
    name: string;
    type: string;
    optional: boolean;
    rest: boolean;
    defaultValue?: string;
  }
  
  export interface MethodOverload {
    signature: string;
    parameters: ParameterInfo[];
    returnType: string;
  }
  
  export interface CallSignatureInfo {
    parameters: ParameterInfo[];
    returnType: string;
    generics: GenericInfo[];
  }
  
  export interface ConstructSignatureInfo {
    parameters: ParameterInfo[];
    returnType: string;
    generics: GenericInfo[];
  }
  
  export interface IndexSignatureInfo {
    keyType: string;
    valueType: string;
    readonly: boolean;
  }
  
  export interface GenericInfo {
    name: string;
    constraint?: string;
    defaultType?: string;
    variance?: 'covariant' | 'contravariant' | 'invariant';
  }
  
  export interface MergedTypeInfo {
    name: string;
    finalType: DeclarationType;
    mergedFrom: string[];
    mergeStrategy: MergeStrategy;
    conflicts: MergeConflict[];
    properties: MergedPropertyInfo[];
    methods: MergedMethodInfo[];
    signatures: MergedSignatureInfo[];
    success: boolean;
    warnings: string[];
    createdAt: Date;
  }
  
  export type MergeStrategy = 
    | 'union' 
    | 'intersection' 
    | 'override' 
    | 'extend' 
    | 'concatenate' 
    | 'conflict';
  
  export interface MergedPropertyInfo extends PropertyInfo {
    sourceDeclarations: string[];
    mergeStrategy: MergeStrategy;
    conflictResolution?: ConflictResolution;
  }
  
  export interface MergedMethodInfo extends MethodInfo {
    sourceDeclarations: string[];
    mergeStrategy: MergeStrategy;
    conflictResolution?: ConflictResolution;
  }
  
  export interface MergedSignatureInfo {
    type: 'call' | 'construct' | 'index';
    signature: string;
    sourceDeclarations: string[];
    mergeStrategy: MergeStrategy;
  }
  
  export interface MergeConflict {
    type: ConflictType;
    severity: 'error' | 'warning' | 'info';
    description: string;
    affectedDeclarations: string[];
    resolution?: ConflictResolution;
    autoResolvable: boolean;
  }
  
  export type ConflictType = 
    | 'property_type_mismatch' 
    | 'method_signature_conflict' 
    | 'accessibility_conflict' 
    | 'modifier_conflict' 
    | 'generic_constraint_conflict' 
    | 'inheritance_conflict';
  
  export interface ConflictResolution {
    strategy: ResolutionStrategy;
    chosen: string;
    reason: string;
    automatic: boolean;
  }
  
  export type ResolutionStrategy = 
    | 'first_wins' 
    | 'last_wins' 
    | 'most_specific' 
    | 'manual_choice' 
    | 'union_types' 
    | 'overload_signatures';
  
  export interface MergeMetrics {
    totalDeclarations: number;
    successfulMerges: number;
    failedMerges: number;
    conflictsResolved: number;
    conflictsPending: number;
    averageMergeTime: number;
    mostMergedType: string;
    lastAnalysis: Date;
  }
  
  // πŸ”§ Declaration Merge Analyzer
  export class MergeAnalyzer {
    private registry: MergeRegistry;
    private conflictResolver: ConflictResolver;
    private mergeStrategies: Map<string, MergeStrategyHandler>;
    
    constructor() {
      this.registry = this.initializeRegistry();
      this.conflictResolver = new ConflictResolver();
      this.mergeStrategies = this.createMergeStrategies();
    }
    
    // πŸ“ Analyze declaration merging
    analyzeDeclarations(declarations: DeclarationInfo[]): MergeAnalysisResult {
      console.log(`πŸ“ Analyzing ${declarations.length} declarations for merging`);
      
      const groupedDeclarations = this.groupDeclarationsByName(declarations);
      const mergeResults: MergedTypeInfo[] = [];
      const conflicts: MergeConflict[] = [];
      
      for (const [name, declarationGroup] of groupedDeclarations) {
        console.log(`πŸ” Analyzing merging for: ${name} (${declarationGroup.length} declarations)`);
        
        const mergeResult = this.analyzeSingleMerge(name, declarationGroup);
        mergeResults.push(mergeResult);
        conflicts.push(...mergeResult.conflicts);
      }
      
      this.updateRegistry(mergeResults, conflicts);
      
      return {
        mergedTypes: mergeResults,
        conflicts,
        metrics: this.calculateMetrics(),
        suggestions: this.generateSuggestions(mergeResults, conflicts),
        generatedAt: new Date()
      };
    }
    
    // πŸ” Analyze a single merge group
    private analyzeSingleMerge(name: string, declarations: DeclarationInfo[]): MergedTypeInfo {
      console.log(`πŸ” Analyzing merge for ${name} with ${declarations.length} declarations`);
      
      if (declarations.length === 1) {
        return this.createSingleDeclarationResult(name, declarations[0]);
      }
      
      // Check merge compatibility
      const compatibility = this.checkMergeCompatibility(declarations);
      if (!compatibility.compatible) {
        return this.createFailedMergeResult(name, declarations, compatibility.conflicts);
      }
      
      // Perform the merge
      const mergeStrategy = this.determineMergeStrategy(declarations);
      const mergedProperties = this.mergeProperties(declarations);
      const mergedMethods = this.mergeMethods(declarations);
      const mergedSignatures = this.mergeSignatures(declarations);
      
      // Detect conflicts
      const conflicts = this.detectConflicts(declarations, mergedProperties, mergedMethods);
      
      return {
        name,
        finalType: this.determineFinalType(declarations),
        mergedFrom: declarations.map(d => `${d.source.file}:${d.source.line}`),
        mergeStrategy,
        conflicts,
        properties: mergedProperties,
        methods: mergedMethods,
        signatures: mergedSignatures,
        success: conflicts.filter(c => c.severity === 'error').length === 0,
        warnings: conflicts.filter(c => c.severity === 'warning').map(c => c.description),
        createdAt: new Date()
      };
    }
    
    // πŸ”§ Merge properties from multiple declarations
    private mergeProperties(declarations: DeclarationInfo[]): MergedPropertyInfo[] {
      const propertyMap = new Map<string, MergedPropertyInfo>();
      
      for (const declaration of declarations) {
        for (const property of declaration.properties) {
          const existing = propertyMap.get(property.name);
          
          if (!existing) {
            propertyMap.set(property.name, {
              ...property,
              sourceDeclarations: [`${declaration.source.file}:${declaration.source.line}`],
              mergeStrategy: 'extend'
            });
          } else {
            // Handle property conflicts
            const mergeResult = this.mergeProperty(existing, property, declaration);
            propertyMap.set(property.name, mergeResult);
          }
        }
      }
      
      return Array.from(propertyMap.values());
    }
    
    // πŸ”§ Merge methods from multiple declarations
    private mergeMethods(declarations: DeclarationInfo[]): MergedMethodInfo[] {
      const methodMap = new Map<string, MergedMethodInfo>();
      
      for (const declaration of declarations) {
        for (const method of declaration.methods) {
          const existing = methodMap.get(method.name);
          
          if (!existing) {
            methodMap.set(method.name, {
              ...method,
              sourceDeclarations: [`${declaration.source.file}:${declaration.source.line}`],
              mergeStrategy: 'extend'
            });
          } else {
            // Handle method overloads
            const mergeResult = this.mergeMethod(existing, method, declaration);
            methodMap.set(method.name, mergeResult);
          }
        }
      }
      
      return Array.from(methodMap.values());
    }
    
    // πŸ”§ Merge signatures from multiple declarations
    private mergeSignatures(declarations: DeclarationInfo[]): MergedSignatureInfo[] {
      const signatures: MergedSignatureInfo[] = [];
      
      for (const declaration of declarations) {
        // Merge call signatures
        for (const callSig of declaration.callSignatures) {
          signatures.push({
            type: 'call',
            signature: this.formatCallSignature(callSig),
            sourceDeclarations: [`${declaration.source.file}:${declaration.source.line}`],
            mergeStrategy: 'concatenate'
          });
        }
        
        // Merge construct signatures
        for (const constructSig of declaration.constructSignatures) {
          signatures.push({
            type: 'construct',
            signature: this.formatConstructSignature(constructSig),
            sourceDeclarations: [`${declaration.source.file}:${declaration.source.line}`],
            mergeStrategy: 'concatenate'
          });
        }
        
        // Merge index signatures
        for (const indexSig of declaration.indexSignatures) {
          signatures.push({
            type: 'index',
            signature: this.formatIndexSignature(indexSig),
            sourceDeclarations: [`${declaration.source.file}:${declaration.source.line}`],
            mergeStrategy: 'union'
          });
        }
      }
      
      return signatures;
    }
    
    // 🚨 Detect conflicts in merged declarations
    private detectConflicts(
      declarations: DeclarationInfo[],
      properties: MergedPropertyInfo[],
      methods: MergedMethodInfo[]
    ): MergeConflict[] {
      const conflicts: MergeConflict[] = [];
      
      // Property type conflicts
      for (const property of properties) {
        if (property.sourceDeclarations.length > 1) {
          const typeConflict = this.checkPropertyTypeConflict(property, declarations);
          if (typeConflict) {
            conflicts.push(typeConflict);
          }
        }
      }
      
      // Method signature conflicts
      for (const method of methods) {
        if (method.sourceDeclarations.length > 1) {
          const signatureConflict = this.checkMethodSignatureConflict(method, declarations);
          if (signatureConflict) {
            conflicts.push(signatureConflict);
          }
        }
      }
      
      // Accessibility conflicts
      const accessibilityConflicts = this.checkAccessibilityConflicts(declarations);
      conflicts.push(...accessibilityConflicts);
      
      return conflicts;
    }
    
    // πŸ” Generate merge suggestions
    generateSuggestions(mergedTypes: MergedTypeInfo[], conflicts: MergeConflict[]): MergeSuggestion[] {
      const suggestions: MergeSuggestion[] = [];
      
      // Suggest automatic conflict resolutions
      for (const conflict of conflicts) {
        if (conflict.autoResolvable && !conflict.resolution) {
          suggestions.push({
            type: 'auto_resolve_conflict',
            description: `Automatically resolve ${conflict.type} conflict`,
            impact: 'low',
            effort: 'minimal',
            conflictId: this.getConflictId(conflict),
            implementation: this.generateConflictResolution(conflict)
          });
        }
      }
      
      // Suggest merge optimizations
      for (const mergedType of mergedTypes) {
        if (mergedType.success && mergedType.methods.length > 10) {
          suggestions.push({
            type: 'optimize_interface',
            description: `Consider splitting ${mergedType.name} into smaller interfaces`,
            impact: 'medium',
            effort: 'moderate',
            implementation: `Split into: ${this.suggestInterfaceSplit(mergedType)}`
          });
        }
      }
      
      // Suggest documentation improvements
      const undocumentedTypes = mergedTypes.filter(t => 
        t.properties.some(p => !p.documentation) || 
        t.methods.some(m => !m.documentation)
      );
      
      if (undocumentedTypes.length > 0) {
        suggestions.push({
          type: 'improve_documentation',
          description: `Add documentation to ${undocumentedTypes.length} merged types`,
          impact: 'high',
          effort: 'moderate',
          implementation: 'Add JSDoc comments to properties and methods'
        });
      }
      
      return suggestions;
    }
    
    // πŸ”§ Helper methods
    private initializeRegistry(): MergeRegistry {
      return {
        declarations: new Map(),
        mergedTypes: new Map(),
        conflicts: [],
        metrics: {
          totalDeclarations: 0,
          successfulMerges: 0,
          failedMerges: 0,
          conflictsResolved: 0,
          conflictsPending: 0,
          averageMergeTime: 0,
          mostMergedType: '',
          lastAnalysis: new Date()
        }
      };
    }
    
    private createMergeStrategies(): Map<string, MergeStrategyHandler> {
      return new Map([
        ['interface', new InterfaceMergeStrategy()],
        ['namespace', new NamespaceMergeStrategy()],
        ['class', new ClassMergeStrategy()],
        ['function', new FunctionMergeStrategy()]
      ]);
    }
    
    private groupDeclarationsByName(declarations: DeclarationInfo[]): Map<string, DeclarationInfo[]> {
      const groups = new Map<string, DeclarationInfo[]>();
      
      for (const declaration of declarations) {
        const key = this.getDeclarationKey(declaration);
        const group = groups.get(key) || [];
        group.push(declaration);
        groups.set(key, group);
      }
      
      return groups;
    }
    
    private getDeclarationKey(declaration: DeclarationInfo): string {
      return `${declaration.namespace || 'global'}.${declaration.name}`;
    }
    
    private checkMergeCompatibility(declarations: DeclarationInfo[]): CompatibilityResult {
      const types = new Set(declarations.map(d => d.type));
      
      // Check if all declarations are of compatible types
      if (types.size > 1) {
        const compatibleCombinations = [
          new Set(['interface', 'namespace']),
          new Set(['function', 'namespace']),
          new Set(['class', 'namespace'])
        ];
        
        const isCompatible = compatibleCombinations.some(combo => 
          types.size === combo.size && [...types].every(type => combo.has(type))
        );
        
        if (!isCompatible) {
          return {
            compatible: false,
            conflicts: [{
              type: 'incompatible_declaration_types',
              severity: 'error',
              description: `Cannot merge declarations of types: ${[...types].join(', ')}`,
              affectedDeclarations: declarations.map(d => `${d.source.file}:${d.source.line}`),
              autoResolvable: false
            }]
          };
        }
      }
      
      return { compatible: true, conflicts: [] };
    }
    
    private determineMergeStrategy(declarations: DeclarationInfo[]): MergeStrategy {
      const types = new Set(declarations.map(d => d.type));
      
      if (types.has('interface')) return 'extend';
      if (types.has('namespace')) return 'concatenate';
      if (types.has('class')) return 'override';
      if (types.has('function')) return 'overload';
      
      return 'union';
    }
    
    private determineFinalType(declarations: DeclarationInfo[]): DeclarationType {
      const types = declarations.map(d => d.type);
      
      // Priority order for determining final type
      const typePriority: DeclarationType[] = [
        'class', 'interface', 'namespace', 'function', 'type', 'enum', 'variable', 'module'
      ];
      
      for (const type of typePriority) {
        if (types.includes(type)) {
          return type;
        }
      }
      
      return types[0];
    }
    
    private createSingleDeclarationResult(name: string, declaration: DeclarationInfo): MergedTypeInfo {
      return {
        name,
        finalType: declaration.type,
        mergedFrom: [`${declaration.source.file}:${declaration.source.line}`],
        mergeStrategy: 'extend',
        conflicts: [],
        properties: declaration.properties.map(p => ({
          ...p,
          sourceDeclarations: [`${declaration.source.file}:${declaration.source.line}`],
          mergeStrategy: 'extend'
        })),
        methods: declaration.methods.map(m => ({
          ...m,
          sourceDeclarations: [`${declaration.source.file}:${declaration.source.line}`],
          mergeStrategy: 'extend'
        })),
        signatures: [],
        success: true,
        warnings: [],
        createdAt: new Date()
      };
    }
    
    private createFailedMergeResult(
      name: string, 
      declarations: DeclarationInfo[], 
      conflicts: MergeConflict[]
    ): MergedTypeInfo {
      return {
        name,
        finalType: declarations[0].type,
        mergedFrom: declarations.map(d => `${d.source.file}:${d.source.line}`),
        mergeStrategy: 'conflict',
        conflicts,
        properties: [],
        methods: [],
        signatures: [],
        success: false,
        warnings: conflicts.map(c => c.description),
        createdAt: new Date()
      };
    }
    
    private mergeProperty(
      existing: MergedPropertyInfo, 
      newProperty: PropertyInfo, 
      declaration: DeclarationInfo
    ): MergedPropertyInfo {
      const sourceDeclaration = `${declaration.source.file}:${declaration.source.line}`;
      
      if (existing.type !== newProperty.type) {
        return {
          ...existing,
          type: `${existing.type} | ${newProperty.type}`,
          sourceDeclarations: [...existing.sourceDeclarations, sourceDeclaration],
          mergeStrategy: 'union',
          conflictResolution: {
            strategy: 'union_types',
            chosen: 'union',
            reason: 'Different types merged into union',
            automatic: true
          }
        };
      }
      
      return {
        ...existing,
        sourceDeclarations: [...existing.sourceDeclarations, sourceDeclaration],
        mergeStrategy: 'extend'
      };
    }
    
    private mergeMethod(
      existing: MergedMethodInfo, 
      newMethod: MethodInfo, 
      declaration: DeclarationInfo
    ): MergedMethodInfo {
      const sourceDeclaration = `${declaration.source.file}:${declaration.source.line}`;
      
      // Add as overload if signatures differ
      if (existing.signature !== newMethod.signature) {
        return {
          ...existing,
          overloads: [
            ...existing.overloads,
            {
              signature: newMethod.signature,
              parameters: newMethod.parameters,
              returnType: newMethod.returnType
            }
          ],
          sourceDeclarations: [...existing.sourceDeclarations, sourceDeclaration],
          mergeStrategy: 'overload_signatures'
        };
      }
      
      return {
        ...existing,
        sourceDeclarations: [...existing.sourceDeclarations, sourceDeclaration],
        mergeStrategy: 'extend'
      };
    }
    
    private formatCallSignature(signature: CallSignatureInfo): string {
      const generics = signature.generics.length > 0 ? 
        `<${signature.generics.map(g => g.name).join(', ')}>` : '';
      const params = signature.parameters.map(p => 
        `${p.name}${p.optional ? '?' : ''}: ${p.type}`
      ).join(', ');
      return `${generics}(${params}): ${signature.returnType}`;
    }
    
    private formatConstructSignature(signature: ConstructSignatureInfo): string {
      const generics = signature.generics.length > 0 ? 
        `<${signature.generics.map(g => g.name).join(', ')}>` : '';
      const params = signature.parameters.map(p => 
        `${p.name}${p.optional ? '?' : ''}: ${p.type}`
      ).join(', ');
      return `new ${generics}(${params}): ${signature.returnType}`;
    }
    
    private formatIndexSignature(signature: IndexSignatureInfo): string {
      const readonly = signature.readonly ? 'readonly ' : '';
      return `${readonly}[key: ${signature.keyType}]: ${signature.valueType}`;
    }
    
    private checkPropertyTypeConflict(
      property: MergedPropertyInfo, 
      declarations: DeclarationInfo[]
    ): MergeConflict | null {
      // Implementation for checking property type conflicts
      return null;
    }
    
    private checkMethodSignatureConflict(
      method: MergedMethodInfo, 
      declarations: DeclarationInfo[]
    ): MergeConflict | null {
      // Implementation for checking method signature conflicts
      return null;
    }
    
    private checkAccessibilityConflicts(declarations: DeclarationInfo[]): MergeConflict[] {
      // Implementation for checking accessibility conflicts
      return [];
    }
    
    private updateRegistry(mergeResults: MergedTypeInfo[], conflicts: MergeConflict[]): void {
      // Update the registry with new merge results
      for (const result of mergeResults) {
        this.registry.mergedTypes.set(result.name, result);
      }
      
      this.registry.conflicts.push(...conflicts);
      this.registry.metrics = this.calculateMetrics();
    }
    
    private calculateMetrics(): MergeMetrics {
      const mergedTypes = Array.from(this.registry.mergedTypes.values());
      const successful = mergedTypes.filter(t => t.success).length;
      const failed = mergedTypes.filter(t => !t.success).length;
      
      return {
        totalDeclarations: this.registry.declarations.size,
        successfulMerges: successful,
        failedMerges: failed,
        conflictsResolved: this.registry.conflicts.filter(c => c.resolution).length,
        conflictsPending: this.registry.conflicts.filter(c => !c.resolution).length,
        averageMergeTime: 0, // Calculate from timing data
        mostMergedType: this.findMostMergedType(mergedTypes),
        lastAnalysis: new Date()
      };
    }
    
    private findMostMergedType(mergedTypes: MergedTypeInfo[]): string {
      return mergedTypes.reduce((max, current) => 
        current.mergedFrom.length > max.mergedFrom.length ? current : max,
        mergedTypes[0]
      )?.name || '';
    }
    
    private getConflictId(conflict: MergeConflict): string {
      return `${conflict.type}_${conflict.affectedDeclarations.join('_')}`;
    }
    
    private generateConflictResolution(conflict: MergeConflict): string {
      // Generate automatic resolution implementation
      return `Resolve ${conflict.type} using ${conflict.resolution?.strategy || 'auto'} strategy`;
    }
    
    private suggestInterfaceSplit(mergedType: MergedTypeInfo): string {
      // Suggest how to split large interfaces
      return `${mergedType.name}Core, ${mergedType.name}Methods, ${mergedType.name}Events`;
    }
  }
  
  // πŸ”§ Supporting classes and interfaces
  abstract class MergeStrategyHandler {
    abstract canMerge(declarations: DeclarationInfo[]): boolean;
    abstract merge(declarations: DeclarationInfo[]): MergedTypeInfo;
  }
  
  class InterfaceMergeStrategy extends MergeStrategyHandler {
    canMerge(declarations: DeclarationInfo[]): boolean {
      return declarations.every(d => d.type === 'interface');
    }
    
    merge(declarations: DeclarationInfo[]): MergedTypeInfo {
      // Interface-specific merging logic
      return {} as MergedTypeInfo;
    }
  }
  
  class NamespaceMergeStrategy extends MergeStrategyHandler {
    canMerge(declarations: DeclarationInfo[]): boolean {
      return declarations.every(d => d.type === 'namespace');
    }
    
    merge(declarations: DeclarationInfo[]): MergedTypeInfo {
      // Namespace-specific merging logic
      return {} as MergedTypeInfo;
    }
  }
  
  class ClassMergeStrategy extends MergeStrategyHandler {
    canMerge(declarations: DeclarationInfo[]): boolean {
      return declarations.some(d => d.type === 'class') && 
             declarations.some(d => d.type === 'namespace');
    }
    
    merge(declarations: DeclarationInfo[]): MergedTypeInfo {
      // Class + namespace merging logic
      return {} as MergedTypeInfo;
    }
  }
  
  class FunctionMergeStrategy extends MergeStrategyHandler {
    canMerge(declarations: DeclarationInfo[]): boolean {
      return declarations.some(d => d.type === 'function') && 
             declarations.some(d => d.type === 'namespace');
    }
    
    merge(declarations: DeclarationInfo[]): MergedTypeInfo {
      // Function + namespace merging logic
      return {} as MergedTypeInfo;
    }
  }
  
  class ConflictResolver {
    resolveConflict(conflict: MergeConflict): ConflictResolution | null {
      switch (conflict.type) {
        case 'property_type_mismatch':
          return this.resolvePropertyTypeConflict(conflict);
        case 'method_signature_conflict':
          return this.resolveMethodSignatureConflict(conflict);
        case 'accessibility_conflict':
          return this.resolveAccessibilityConflict(conflict);
        default:
          return null;
      }
    }
    
    private resolvePropertyTypeConflict(conflict: MergeConflict): ConflictResolution {
      return {
        strategy: 'union_types',
        chosen: 'union',
        reason: 'Create union type to accommodate all variants',
        automatic: true
      };
    }
    
    private resolveMethodSignatureConflict(conflict: MergeConflict): ConflictResolution {
      return {
        strategy: 'overload_signatures',
        chosen: 'overloads',
        reason: 'Create method overloads for different signatures',
        automatic: true
      };
    }
    
    private resolveAccessibilityConflict(conflict: MergeConflict): ConflictResolution {
      return {
        strategy: 'most_specific',
        chosen: 'public',
        reason: 'Use most permissive accessibility level',
        automatic: false
      };
    }
  }
  
  // πŸ“Š Supporting interfaces
  interface CompatibilityResult {
    compatible: boolean;
    conflicts: MergeConflict[];
  }
  
  interface MergeAnalysisResult {
    mergedTypes: MergedTypeInfo[];
    conflicts: MergeConflict[];
    metrics: MergeMetrics;
    suggestions: MergeSuggestion[];
    generatedAt: Date;
  }
  
  interface MergeSuggestion {
    type: 'auto_resolve_conflict' | 'optimize_interface' | 'improve_documentation' | 'refactor_types';
    description: string;
    impact: 'low' | 'medium' | 'high';
    effort: 'minimal' | 'moderate' | 'significant';
    conflictId?: string;
    implementation: string;
  }
}

// πŸš€ Usage examples with the management system
const mergeAnalyzer = new DeclarationMerging.MergeAnalyzer();

// Example declarations to analyze
const sampleDeclarations: DeclarationMerging.DeclarationInfo[] = [
  {
    name: 'User',
    type: 'interface',
    source: { file: 'user.ts', line: 1, column: 1, length: 100 },
    properties: [
      {
        name: 'id',
        type: 'string',
        optional: false,
        readonly: true,
        static: false,
        accessibility: 'public',
        decorators: []
      }
    ],
    methods: [],
    callSignatures: [],
    constructSignatures: [],
    indexSignatures: [],
    generics: [],
    extends: [],
    implements: [],
    accessibility: 'public',
    exported: true,
    ambient: false,
    createdAt: new Date()
  },
  {
    name: 'User',
    type: 'interface',
    source: { file: 'user-profile.ts', line: 5, column: 1, length: 200 },
    properties: [
      {
        name: 'profile',
        type: 'UserProfile',
        optional: false,
        readonly: false,
        static: false,
        accessibility: 'public',
        decorators: []
      }
    ],
    methods: [],
    callSignatures: [],
    constructSignatures: [],
    indexSignatures: [],
    generics: [],
    extends: [],
    implements: [],
    accessibility: 'public',
    exported: true,
    ambient: false,
    createdAt: new Date()
  }
];

// Analyze the declarations
const analysisResult = mergeAnalyzer.analyzeDeclarations(sampleDeclarations);
console.log('Merge analysis result:', analysisResult);

🎨 Real-World Declaration Merging Examples

// 🌟 Extending popular libraries with declaration merging

// Extending Express.js Request interface across multiple files
// File: express-user.d.ts
declare module 'express-serve-static-core' {
  interface Request {
    user?: {
      id: string;
      email: string;
      role: 'admin' | 'user' | 'moderator';
    };
  }
}

// File: express-session.d.ts
declare module 'express-serve-static-core' {
  interface Request {
    sessionId: string;
    sessionData: SessionData;
  }
  
  interface Response {
    sendSuccess<T>(data: T, message?: string): Response;
    sendError(error: string, statusCode?: number): Response;
  }
}

interface SessionData {
  startTime: Date;
  lastActivity: Date;
  ipAddress: string;
  userAgent: string;
  preferences: UserPreferences;
}

interface UserPreferences {
  language: string;
  timezone: string;
  theme: 'light' | 'dark';
  notifications: boolean;
}

// File: express-validation.d.ts
declare module 'express-serve-static-core' {
  interface Request {
    validatedBody?: any;
    validationErrors?: ValidationError[];
    validate<T>(schema: ValidationSchema<T>): Promise<T>;
  }
}

interface ValidationError {
  field: string;
  message: string;
  value: any;
  code: string;
}

interface ValidationSchema<T> {
  [K in keyof T]: FieldValidator<T[K]>;
}

interface FieldValidator<T> {
  type: string;
  required?: boolean;
  min?: number;
  max?: number;
  pattern?: RegExp;
  custom?: (value: T) => boolean | Promise<boolean>;
}

// Now all these extensions are merged into a single Request interface
// Usage in middleware:
const authMiddleware = (req: Request, res: Response, next: NextFunction) => {
  // All merged properties are available with full type safety
  console.log('User:', req.user?.email);
  console.log('Session ID:', req.sessionId);
  console.log('Validation errors:', req.validationErrors);
  
  if (!req.user) {
    return res.sendError('Authentication required', 401);
  }
  
  next();
};

// 🎯 Complex namespace merging across modules
// File: database-core.ts
namespace DatabaseAPI {
  export interface Connection {
    host: string;
    port: number;
    database: string;
    ssl?: boolean;
  }
  
  export interface QueryResult<T> {
    rows: T[];
    count: number;
    duration: number;
  }
  
  export function connect(config: Connection): Promise<Client> {
    return Promise.resolve(new ClientImpl(config));
  }
  
  class ClientImpl implements Client {
    constructor(private config: Connection) {}
    
    async query<T>(sql: string, params?: any[]): Promise<QueryResult<T>> {
      return {
        rows: [],
        count: 0,
        duration: 0
      };
    }
    
    async close(): Promise<void> {
      // Close connection
    }
  }
  
  export interface Client {
    query<T>(sql: string, params?: any[]): Promise<QueryResult<T>>;
    close(): Promise<void>;
  }
}

// File: database-transactions.ts
namespace DatabaseAPI {
  export interface TransactionOptions {
    isolation?: IsolationLevel;
    timeout?: number;
    readOnly?: boolean;
  }
  
  export type IsolationLevel = 
    | 'READ_UNCOMMITTED'
    | 'READ_COMMITTED' 
    | 'REPEATABLE_READ' 
    | 'SERIALIZABLE';
  
  export interface Transaction extends Client {
    commit(): Promise<void>;
    rollback(): Promise<void>;
    savepoint(name: string): Promise<void>;
    rollbackToSavepoint(name: string): Promise<void>;
  }
  
  // Extend the existing Client interface
  export interface Client {
    transaction<T>(
      callback: (tx: Transaction) => Promise<T>,
      options?: TransactionOptions
    ): Promise<T>;
  }
  
  export function createTransaction(client: Client, options?: TransactionOptions): Transaction {
    return new TransactionImpl(client, options);
  }
  
  class TransactionImpl implements Transaction {
    constructor(
      private client: Client, 
      private options?: TransactionOptions
    ) {}
    
    async query<T>(sql: string, params?: any[]): Promise<QueryResult<T>> {
      return this.client.query<T>(sql, params);
    }
    
    async commit(): Promise<void> {
      await this.client.query('COMMIT');
    }
    
    async rollback(): Promise<void> {
      await this.client.query('ROLLBACK');
    }
    
    async savepoint(name: string): Promise<void> {
      await this.client.query(`SAVEPOINT ${name}`);
    }
    
    async rollbackToSavepoint(name: string): Promise<void> {
      await this.client.query(`ROLLBACK TO SAVEPOINT ${name}`);
    }
    
    async close(): Promise<void> {
      await this.client.close();
    }
    
    async transaction<T>(
      callback: (tx: Transaction) => Promise<T>,
      options?: TransactionOptions
    ): Promise<T> {
      // Nested transaction implementation
      return callback(this);
    }
  }
}

// File: database-migrations.ts
namespace DatabaseAPI {
  export interface Migration {
    version: string;
    name: string;
    up: (client: Client) => Promise<void>;
    down: (client: Client) => Promise<void>;
  }
  
  export interface MigrationRunner {
    run(migrations: Migration[]): Promise<MigrationResult>;
    rollback(steps?: number): Promise<MigrationResult>;
    reset(): Promise<MigrationResult>;
    status(): Promise<MigrationStatus>;
  }
  
  export interface MigrationResult {
    applied: string[];
    failed: string[];
    errors: MigrationError[];
    duration: number;
  }
  
  export interface MigrationStatus {
    current: string;
    pending: string[];
    applied: string[];
  }
  
  export interface MigrationError {
    migration: string;
    error: string;
    sql?: string;
  }
  
  // Extend Client with migration capabilities
  export interface Client {
    migrate(): MigrationRunner;
  }
  
  export function createMigrationRunner(client: Client): MigrationRunner {
    return new MigrationRunnerImpl(client);
  }
  
  class MigrationRunnerImpl implements MigrationRunner {
    constructor(private client: Client) {}
    
    async run(migrations: Migration[]): Promise<MigrationResult> {
      const result: MigrationResult = {
        applied: [],
        failed: [],
        errors: [],
        duration: 0
      };
      
      const start = Date.now();
      
      for (const migration of migrations) {
        try {
          await migration.up(this.client);
          result.applied.push(migration.version);
        } catch (error) {
          result.failed.push(migration.version);
          result.errors.push({
            migration: migration.version,
            error: error instanceof Error ? error.message : String(error)
          });
        }
      }
      
      result.duration = Date.now() - start;
      return result;
    }
    
    async rollback(steps: number = 1): Promise<MigrationResult> {
      // Rollback implementation
      return {
        applied: [],
        failed: [],
        errors: [],
        duration: 0
      };
    }
    
    async reset(): Promise<MigrationResult> {
      // Reset implementation
      return {
        applied: [],
        failed: [],
        errors: [],
        duration: 0
      };
    }
    
    async status(): Promise<MigrationStatus> {
      // Status implementation
      return {
        current: '001',
        pending: [],
        applied: ['001']
      };
    }
  }
}

// Now DatabaseAPI namespace contains all merged functionality
const dbUsage = async () => {
  const client = await DatabaseAPI.connect({
    host: 'localhost',
    port: 5432,
    database: 'myapp'
  });
  
  // Use core functionality
  const users = await client.query<User>('SELECT * FROM users');
  
  // Use transaction functionality (merged)
  await client.transaction(async (tx) => {
    await tx.query('INSERT INTO logs VALUES (?)', ['Transaction started']);
    await tx.commit();
  });
  
  // Use migration functionality (merged)
  const migrationRunner = client.migrate();
  await migrationRunner.run([]);
  
  await client.close();
};

// πŸ”₯ Advanced function and namespace merging
function Logger(name: string): Logger.Instance {
  return new Logger.LoggerImpl(name);
}

namespace Logger {
  export interface Instance {
    debug(message: string, meta?: any): void;
    info(message: string, meta?: any): void;
    warn(message: string, meta?: any): void;
    error(message: string, error?: Error): void;
    child(context: Record<string, any>): Instance;
  }
  
  export interface LogEntry {
    level: LogLevel;
    message: string;
    timestamp: Date;
    context: Record<string, any>;
    meta?: any;
  }
  
  export type LogLevel = 'debug' | 'info' | 'warn' | 'error';
  
  export interface LoggerConfig {
    level: LogLevel;
    format: 'json' | 'text' | 'structured';
    transports: Transport[];
    context?: Record<string, any>;
  }
  
  export interface Transport {
    type: 'console' | 'file' | 'http' | 'syslog';
    level?: LogLevel;
    config: any;
  }
  
  export class LoggerImpl implements Instance {
    private context: Record<string, any> = {};
    
    constructor(
      private name: string,
      private config: LoggerConfig = Logger.defaultConfig
    ) {}
    
    debug(message: string, meta?: any): void {
      this.log('debug', message, meta);
    }
    
    info(message: string, meta?: any): void {
      this.log('info', message, meta);
    }
    
    warn(message: string, meta?: any): void {
      this.log('warn', message, meta);
    }
    
    error(message: string, error?: Error): void {
      this.log('error', message, error);
    }
    
    child(context: Record<string, any>): Instance {
      return new LoggerImpl(this.name, {
        ...this.config,
        context: { ...this.context, ...context }
      });
    }
    
    private log(level: LogLevel, message: string, meta?: any): void {
      const entry: LogEntry = {
        level,
        message,
        timestamp: new Date(),
        context: { ...this.context, logger: this.name },
        meta
      };
      
      // Process through transports
      for (const transport of this.config.transports) {
        if (this.shouldLog(level, transport.level)) {
          this.writeToTransport(transport, entry);
        }
      }
    }
    
    private shouldLog(level: LogLevel, transportLevel?: LogLevel): boolean {
      const levels = ['debug', 'info', 'warn', 'error'];
      const currentIndex = levels.indexOf(level);
      const minIndex = levels.indexOf(transportLevel || this.config.level);
      return currentIndex >= minIndex;
    }
    
    private writeToTransport(transport: Transport, entry: LogEntry): void {
      // Transport-specific writing logic
      switch (transport.type) {
        case 'console':
          console.log(this.formatEntry(entry));
          break;
        case 'file':
          // File writing logic
          break;
        case 'http':
          // HTTP transport logic
          break;
        case 'syslog':
          // Syslog transport logic
          break;
      }
    }
    
    private formatEntry(entry: LogEntry): string {
      switch (this.config.format) {
        case 'json':
          return JSON.stringify(entry);
        case 'text':
          return `[${entry.timestamp.toISOString()}] ${entry.level.toUpperCase()}: ${entry.message}`;
        case 'structured':
          return `${entry.timestamp.toISOString()} | ${entry.level.padEnd(5)} | ${entry.context.logger} | ${entry.message}`;
        default:
          return entry.message;
      }
    }
  }
  
  export const defaultConfig: LoggerConfig = {
    level: 'info',
    format: 'text',
    transports: [
      {
        type: 'console',
        config: {}
      }
    ]
  };
  
  export function configure(config: Partial<LoggerConfig>): void {
    Object.assign(defaultConfig, config);
  }
  
  export function createLogger(name: string, config?: LoggerConfig): Instance {
    return new LoggerImpl(name, config || defaultConfig);
  }
  
  export const root = createLogger('root');
}

// Usage of merged function and namespace
const appLogger = Logger('App'); // Function call
const serviceLogger = Logger.createLogger('Service', { // Namespace method
  level: 'debug',
  format: 'json',
  transports: [
    { type: 'console', config: {} },
    { type: 'file', config: { filename: 'app.log' } }
  ]
});

Logger.configure({ level: 'warn' }); // Namespace static method
const childLogger = appLogger.child({ requestId: '123' }); // Instance method

πŸ§ͺ Testing Declaration Merging

// πŸ§ͺ Comprehensive testing for declaration merging

import { describe, it, expect, beforeEach } from '@jest/globals';

describe('Declaration Merging', () => {
  describe('Interface Merging', () => {
    it('should merge interface properties correctly', () => {
      // Define interfaces in different scopes to test merging
      interface TestInterface {
        prop1: string;
      }
      
      interface TestInterface {
        prop2: number;
      }
      
      interface TestInterface {
        prop3: boolean;
      }
      
      // Test that all properties are available
      const testObj: TestInterface = {
        prop1: 'hello',
        prop2: 42,
        prop3: true
      };
      
      expect(testObj.prop1).toBe('hello');
      expect(testObj.prop2).toBe(42);
      expect(testObj.prop3).toBe(true);
    });
    
    it('should merge interface methods correctly', () => {
      interface Calculator {
        add(a: number, b: number): number;
      }
      
      interface Calculator {
        subtract(a: number, b: number): number;
      }
      
      interface Calculator {
        multiply(a: number, b: number): number;
        divide(a: number, b: number): number;
      }
      
      class CalculatorImpl implements Calculator {
        add(a: number, b: number): number {
          return a + b;
        }
        
        subtract(a: number, b: number): number {
          return a - b;
        }
        
        multiply(a: number, b: number): number {
          return a * b;
        }
        
        divide(a: number, b: number): number {
          return a / b;
        }
      }
      
      const calc = new CalculatorImpl();
      expect(calc.add(2, 3)).toBe(5);
      expect(calc.subtract(5, 2)).toBe(3);
      expect(calc.multiply(3, 4)).toBe(12);
      expect(calc.divide(10, 2)).toBe(5);
    });
    
    it('should handle method overloads in merged interfaces', () => {
      interface Formatter {
        format(value: string): string;
      }
      
      interface Formatter {
        format(value: number): string;
      }
      
      interface Formatter {
        format(value: Date): string;
      }
      
      class FormatterImpl implements Formatter {
        format(value: string | number | Date): string {
          if (typeof value === 'string') {
            return value.toUpperCase();
          }
          if (typeof value === 'number') {
            return value.toFixed(2);
          }
          if (value instanceof Date) {
            return value.toISOString();
          }
          return String(value);
        }
      }
      
      const formatter = new FormatterImpl();
      expect(formatter.format('hello')).toBe('HELLO');
      expect(formatter.format(42.567)).toBe('42.57');
      expect(formatter.format(new Date('2023-01-01'))).toContain('2023-01-01');
    });
  });
  
  describe('Namespace Merging', () => {
    it('should merge namespace exports correctly', () => {
      namespace TestNamespace {
        export const value1 = 'test1';
        export function func1(): string {
          return 'func1';
        }
      }
      
      namespace TestNamespace {
        export const value2 = 'test2';
        export function func2(): string {
          return 'func2';
        }
      }
      
      namespace TestNamespace {
        export interface Config {
          setting1: string;
          setting2: number;
        }
        
        export function configure(config: Config): void {
          // Configuration logic
        }
      }
      
      // All exports should be available
      expect(TestNamespace.value1).toBe('test1');
      expect(TestNamespace.value2).toBe('test2');
      expect(TestNamespace.func1()).toBe('func1');
      expect(TestNamespace.func2()).toBe('func2');
      
      const config: TestNamespace.Config = {
        setting1: 'value',
        setting2: 42
      };
      
      expect(() => {
        TestNamespace.configure(config);
      }).not.toThrow();
    });
    
    it('should merge nested namespaces correctly', () => {
      namespace OuterNamespace {
        export namespace Inner {
          export const prop1 = 'inner1';
        }
      }
      
      namespace OuterNamespace {
        export namespace Inner {
          export const prop2 = 'inner2';
        }
        
        export namespace Another {
          export const prop3 = 'another';
        }
      }
      
      expect(OuterNamespace.Inner.prop1).toBe('inner1');
      expect(OuterNamespace.Inner.prop2).toBe('inner2');
      expect(OuterNamespace.Another.prop3).toBe('another');
    });
  });
  
  describe('Function and Namespace Merging', () => {
    it('should merge function with namespace correctly', () => {
      function TestFunction(input: string): string {
        return `processed: ${input}`;
      }
      
      namespace TestFunction {
        export interface Options {
          uppercase: boolean;
          prefix: string;
        }
        
        export function withOptions(input: string, options: Options): string {
          let result = input;
          if (options.uppercase) {
            result = result.toUpperCase();
          }
          return `${options.prefix}${result}`;
        }
        
        export const defaultOptions: Options = {
          uppercase: false,
          prefix: ''
        };
      }
      
      // Test function call
      expect(TestFunction('hello')).toBe('processed: hello');
      
      // Test namespace properties and methods
      expect(TestFunction.withOptions('hello', { uppercase: true, prefix: 'TEST: ' }))
        .toBe('TEST: HELLO');
      expect(TestFunction.defaultOptions.uppercase).toBe(false);
    });
  });
  
  describe('Class and Namespace Merging', () => {
    it('should merge class with namespace correctly', () => {
      class TestClass {
        constructor(public value: string) {}
        
        getValue(): string {
          return this.value;
        }
      }
      
      namespace TestClass {
        export interface Config {
          defaultValue: string;
          validator?: (value: string) => boolean;
        }
        
        export function create(config: Config): TestClass {
          const value = config.defaultValue;
          if (config.validator && !config.validator(value)) {
            throw new Error('Invalid default value');
          }
          return new TestClass(value);
        }
        
        export function isValid(instance: TestClass): boolean {
          return instance.getValue().length > 0;
        }
      }
      
      // Test class instantiation
      const instance1 = new TestClass('direct');
      expect(instance1.getValue()).toBe('direct');
      
      // Test namespace factory method
      const instance2 = TestClass.create({
        defaultValue: 'factory',
        validator: (value) => value.length > 5
      });
      expect(instance2.getValue()).toBe('factory');
      
      // Test namespace utility method
      expect(TestClass.isValid(instance1)).toBe(true);
      expect(TestClass.isValid(new TestClass(''))).toBe(false);
    });
  });
  
  describe('Module Augmentation with Declaration Merging', () => {
    it('should extend library types correctly', () => {
      // Simulate extending a library interface
      interface LibraryType {
        existingMethod(): string;
      }
      
      // Extend the interface (simulating multiple files)
      interface LibraryType {
        newMethod(): number;
      }
      
      interface LibraryType {
        anotherMethod(param: boolean): void;
      }
      
      class LibraryTypeImpl implements LibraryType {
        existingMethod(): string {
          return 'existing';
        }
        
        newMethod(): number {
          return 42;
        }
        
        anotherMethod(param: boolean): void {
          console.log(`Called with ${param}`);
        }
      }
      
      const lib = new LibraryTypeImpl();
      expect(lib.existingMethod()).toBe('existing');
      expect(lib.newMethod()).toBe(42);
      expect(() => lib.anotherMethod(true)).not.toThrow();
    });
  });
  
  describe('Error Cases and Edge Cases', () => {
    it('should handle conflicting property types', () => {
      // This would cause a TypeScript error in real usage
      // but we can test the concept
      interface ConflictTest {
        prop: string;
      }
      
      // In a real scenario, this would conflict:
      // interface ConflictTest {
      //   prop: number; // Error: Subsequent property declarations must have the same type
      // }
      
      // Instead, we test union types as a resolution
      interface UnionTest {
        prop: string | number;
      }
      
      const unionObj: UnionTest = { prop: 'string' };
      expect(typeof unionObj.prop).toBe('string');
      
      const unionObj2: UnionTest = { prop: 42 };
      expect(typeof unionObj2.prop).toBe('number');
    });
    
    it('should handle complex inheritance scenarios', () => {
      interface Base {
        baseMethod(): void;
      }
      
      interface Extended extends Base {
        extendedMethod(): void;
      }
      
      // Merge additional methods into Extended
      interface Extended {
        additionalMethod(): void;
      }
      
      class ExtendedImpl implements Extended {
        baseMethod(): void {
          console.log('base');
        }
        
        extendedMethod(): void {
          console.log('extended');
        }
        
        additionalMethod(): void {
          console.log('additional');
        }
      }
      
      const obj = new ExtendedImpl();
      expect(() => {
        obj.baseMethod();
        obj.extendedMethod();
        obj.additionalMethod();
      }).not.toThrow();
    });
  });
});

// πŸ“Š Performance testing for declaration merging
describe('Declaration Merging Performance', () => {
  it('should handle large interface merges efficiently', () => {
    // Create a large interface through merging
    interface LargeInterface {
      prop1: string;
    }
    
    // Simulate many merges
    for (let i = 2; i <= 100; i++) {
      eval(`
        interface LargeInterface {
          prop${i}: string;
        }
      `);
    }
    
    // Test that TypeScript can handle the merged interface
    const testCreation = () => {
      const obj: Partial<LargeInterface> = {};
      for (let i = 1; i <= 100; i++) {
        (obj as any)[`prop${i}`] = `value${i}`;
      }
      return obj;
    };
    
    const start = performance.now();
    const largeObj = testCreation();
    const end = performance.now();
    
    expect(end - start).toBeLessThan(100); // Should complete quickly
    expect(Object.keys(largeObj).length).toBe(100);
  });
});

🎯 Conclusion

Congratulations! You’ve now mastered the sophisticated art of declaration merging in TypeScript! πŸŽ‰

Throughout this tutorial, you’ve learned how to:

  • Master all types of declaration merging including interfaces, namespaces, functions, and classes
  • Safely extend existing types and third-party library definitions without breaking compatibility
  • Build comprehensive management systems for tracking and analyzing declaration merging in large projects
  • Handle complex merging scenarios with conflicts, resolutions, and optimization strategies
  • Create flexible type architectures that can grow and evolve through strategic merging

Declaration merging is one of TypeScript’s most powerful features, enabling you to create extensible, modular type systems that can adapt to changing requirements. The key is to use it thoughtfully, with proper analysis, conflict resolution, and documentation to ensure your merged declarations remain maintainable and understandable.

Remember: declaration merging is about enhancement and extension, not replacement. Always strive to maintain backward compatibility and clear semantic meaning when merging declarations. With the management system and testing strategies you’ve learned, you can confidently use declaration merging to create exactly the type system you need while maintaining the highest standards of code quality.

Keep practicing these patterns, and you’ll find that declaration merging becomes an invaluable tool for creating flexible, extensible, and maintainable type systems that can adapt to any requirement! πŸš€

πŸ“š Additional Resources