Extend a third-party API
A library exposes a class or interface that application code needs to extend with project-specific members.
TypeScript · Function
Module augmentation lets a module add type declarations to an existing module's named exports. The declarations merge with the original API, while any runtime patch must be implemented and loaded separately.
A module augmentation reopens an existing module with declare module and adds declarations that merge with its original named exports. The augmentation changes TypeScript's view of the module; runtime behavior still requires an implementation, usually installed by importing a patch module.
declare module "module-specifier" {
// declarations that patch existing named exports
}| Name | Type | Description |
|---|---|---|
module specifier | string literal | The module specifier naming the existing module whose declarations will be extended. |
augmentation body | declarations | Existing named declarations to merge into the target module. |
The augmentation contributes merged type declarations to the named exports of an existing module; it does not itself produce a runtime value.
// observable.ts
export class Observable<T> {
constructor(public value: 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 <T, U>(
this: Observable<T>, f: (x: T) => U,
) {
return new Observable(f(this.value));
};
// consumer.ts
import { Observable } from "./observable";
import "./map";
const result = new Observable(1).map(x => x.toFixed());
console.log(result.value);The augmentation adds the map method to Observable's type, while the imported patch supplies its runtime implementation.
A library exposes a class or interface that application code needs to extend with project-specific members.
A separate JavaScript file adds a method to an imported class prototype.
A module needs to add members to global types from within module code.
Use declare module with the target module specifier, then write compatible declarations inside it. TypeScript merges those declarations with the original module as though they were declared in the same file.
Follow-up: Can the augmentation add a new exported function? No. It can only patch an existing declaration, not add a new top-level declaration.
The augmentation supplies type information only. If the added method or property must work at runtime, code must also patch the actual object or prototype, and consumers must load that patch.
Follow-up: Why might a type-checking example still fail at runtime? The declaration merge does not create JavaScript; the implementation module must be executed.
Only named exports can be augmented. Default exports cannot be addressed by exported name because default is reserved, so they are excluded by this feature.
Follow-up: What design alternative helps extensibility? Expose a named class, interface, or function that consumers can augment instead of relying on a default export.
Declaration mergingGlobal augmentationModulesAmbient module declarations