TypeScript merges multiple declarations of the same name.

Interface Merging

interface User {
  name: string;
}

interface User {
  age: number;
}

// Merged: { name: string; age: number; }
const user: User = {
  name: "Alice",
  age: 25
};

Merging with Different Property Types

interface Document {
  createElement(tagName: "div"): HTMLDivElement;
  createElement(tagName: "span"): HTMLSpanElement;
}

interface Document {
  createElement(tagName: "a"): HTMLAnchorElement;
}

// All overloads are merged

Namespace Merging

namespace Geometry {
  export function area() {
    // ...
  }
}

namespace Geometry {
  export function perimeter() {
    // ...
  }
}

// Both functions are available
Geometry.area();
Geometry.perimeter();

Class and Interface Merging

class Album {
  label: Album.AlbumLabel;
}

namespace Album {
  export class AlbumLabel {
    // ...
  }
}

// Album class has label property of type Album.AlbumLabel

Enum Merging

enum Color {
  Red,
  Green
}

enum Color {
  Blue = 2,
  Yellow
}

// Merged enum: Red=0, Green=1, Blue=2, Yellow=3

Module and Namespace Merging

// shapes.ts
export class Triangle {
  // ...
}

// augmentation.ts
import { Triangle } from "./shapes";

declare module "./shapes" {
  namespace Triangle {
    export function create(): Triangle;
  }
}

Triangle.create(); // Available after augmentation

Exercises

Exercise 1: Interface Merging

// Create an interface in one file
// Extend it in another file using declaration merging
// Use the merged interface

Exercise 2: Namespace Merging

// Create a namespace with some exports
// Extend it in another file
// Use all merged exports

Exercise 3: Class and Namespace

// Create a class
// Add static methods via namespace merging
// Use both instance and static methods

Exercise 4: Module Augmentation

// Augment a module's exports
// Add new interfaces and types
// Use them in your code

Exercise 5: Complex Merging

// Combine interface, namespace, and module merging
// Create a comprehensive example

Best Practices

  1. Use for extensibility - When you need to extend types
  2. Document merges - Explain what's being merged
  3. Avoid conflicts - Don't create incompatible merges
  4. Use namespaces - For organizing related types
  5. Be careful with enums - Enum merging can be confusing

Common Mistakes

  1. Conflicting property types
// ❌ Error: Property 'x' must be of type 'string'
interface A {
  x: string;
}

interface A {
  x: number; // Conflict!
}
  1. Merging non-mergable declarations
// ❌ Can't merge type aliases
type A = string;
type A = number; // Error
  1. Namespace conflicts
// ❌ Conflicting exports
namespace N {
  export const x = 1;
}

namespace N {
  export const x = 2; // Error: Duplicate identifier
}

Next Steps

Learn about Branded Types and Opaque Types.