# TypeScript Declaration Merging

Declaration merging is a unique feature in TypeScript where the compiler merges two or more separate declarations declared with the same name into a single definition. This concept is fundamental to how TypeScript models existing JavaScript libraries and allows for extensibility.

## 1. Merging Interfaces

The most common type of merging is interface merging. This allows you to add members to an interface declared elsewhere.

```typescript
interface Box {
    height: number;
    width: number;
}

interface Box {
    scale: number;
}

let box: Box = { height: 5, width: 6, scale: 10 };
```

### Rules
*   **Non-function members** must be unique. If they are not unique, they must have the same type. If they have different types, the compiler will issue an error.
*   **Function members** (methods) are treated as overloads.

## 2. Merging Namespaces

Namespaces with the same name will merge their exported members.

```typescript
namespace Animals {
    export class Zebra { }
}

namespace Animals {
    export interface Legged { numberOfLegs: number; }
    export class Dog { }
}

// Result: Animals namespace has Zebra, Legged, and Dog.
```

## 3. Merging Namespaces with Classes, Functions, and Enums

This pattern allows you to describe inner classes or static properties using namespaces.

### Class + Namespace
This is often used to add "static" inner classes or types to a class.

```typescript
class Album {
    label: Album.AlbumLabel;
}

namespace Album {
    export class AlbumLabel { }
}
```

### Function + Namespace
This allows you to add properties to a function (since functions are objects in JavaScript).

```typescript
function buildLabel(name: string): string {
    return buildLabel.prefix + name + buildLabel.suffix;
}

namespace buildLabel {
    export let suffix = "";
    export let prefix = "Hello, ";
}

console.log(buildLabel("Sam")); // "Hello, Sam"
```

### Enum + Namespace
This allows you to add static methods to an enum.

```typescript
enum Color {
    Red = 1,
    Green = 2,
    Blue = 4
}

namespace Color {
    export function mixColor(colorName: string) {
        if (colorName == "Yellow") {
            return Color.Red + Color.Green;
        }
        // ...
    }
}
```

## 4. Module Augmentation

Although modules do not support merging in the same way (because they create their own scope), you can patch existing modules using `declare module`.

```typescript
// observable.ts
export class Observable<T> {
    // ... implementation ...
}

// map.ts
import { Observable } from "./observable";

declare module "./observable" {
    interface Observable<T> {
        map<U>(f: (x: T) => U): Observable<U>;
    }
}

Observable.prototype.map = function(f) {
    // ... implementation ...
}
```

## 5. Disallowed Merges

Not all merges are allowed. For example, you cannot merge classes with classes (use Mixins instead) or variables with variables.

[[programming/javascript/typescript/typescript]]
[[programming/javascript/typescript/modules-and-namespaces]]