Declaration merging

In TypeScript, a declaration creates entities in
at least one of three groups: namespace, type,
or value.

Merging Interfaces

The merge mechanically joins the members of both
declarations into a single interface with the
same name.

Merging Namespaces

Since namespaces create both a namespace and a
value.
To merge the namespaces, type definitions from
exported interfaces declared in each namespace
are themselves merged, forming a single namespace
with merged interface definitions inside.
To merge the namespace value, at each declaration
site, if a namespace already exists with the given
name, it is further extended by taking the
existing namespace and adding the exported members
of the second namespace to the first.
Non-exported members are only visible in the
original (un-merged) namespace.

Module augmentation

// observable.ts
export class Observable<T> {}

// 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) {};

// consumer.ts
import { Observable } from "./observable";
import "./map";
let o: Observable<number>;
o.map((x) => x.toFixed());

Global augmentation

You can also add declarations to the global scope
from inside a module:

// observable.ts
export class Observable<T> {}

declare global {
  interface Array<T> {
    toObservable(): Observable<T>;
  }
}

Array.prototype.toObservable = function () {};