Skip to content
masterclassBuddyTech Buzz5 fresh blogs · 5:00 AM IST

TypeScript · Function

Module Augmentation

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.

How it works

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.

Syntax

declare module "module-specifier" {
  // declarations that patch existing named exports
}

Parameters

NameTypeDescription
module specifierstring literalThe module specifier naming the existing module whose declarations will be extended.
augmentation bodydeclarationsExisting named declarations to merge into the target module.

Returns

The augmentation contributes merged type declarations to the named exports of an existing module; it does not itself produce a runtime value.

Key points

  • The compiler combines augmentation declarations with the target module's declarations, giving consumers the extended type.
  • Runtime extension is achieved separately by importing the object and modifying it, such as adding a prototype method.
  • The declaration uses ambient-module syntax: declare module followed by the module specifier and an augmentation body.
  • Resolution uses the same rules as ordinary module references, so the specifier must identify the existing module.

Common mistakes

  • An augmentation cannot introduce a new top-level export; it may only modify declarations that already exist in the target module.
  • Default exports cannot be augmented, so design the target API around named exports when extension is required.
  • The string in declare module follows normal import/export module-specifier resolution; an incorrect specifier targets nothing useful.

Example: Augmenting an Observable module

// 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.

When to use it

Extend a third-party API

A library exposes a class or interface that application code needs to extend with project-specific members.

Describe a runtime patch

A separate JavaScript file adds a method to an imported class prototype.

Augment global scope

A module needs to add members to global types from within module code.

Interview questions

QHow does module augmentation work?

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.

QDoes module augmentation implement the added behavior?

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.

QWhat export limitation applies?

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 merging
  • Global augmentation
  • Modules
  • Ambient module declarations

Source: Declaration Merging. Checked 2026-10-15.