SyntaxStudy
Sign Up
TypeScript Module Augmentation and Ambient Declarations
TypeScript Beginner 1 min read

Module Augmentation and Ambient Declarations

Module augmentation allows you to add new declarations to an existing module without modifying its source code. This is done in a declaration file or a regular TypeScript file by importing the module and then using declare module with the same module specifier. The augmented declarations are merged with the original at compile time. This technique is used by popular libraries to provide optional type extensions. Ambient declarations describe the shape of code that exists in the runtime environment but was not written in TypeScript. Declaration files (.d.ts) contain only type information and no implementation. They are how TypeScript understands JavaScript libraries, global browser APIs, and Node.js built-ins. The definitely-typed project (@types/*) provides community-maintained declaration files for thousands of packages. Global augmentation lets you add properties to the global scope or extend existing global types like Window, process.env, or Array.prototype. This is useful for application-specific globals — such as a debug flag or a custom analytics object — that are injected by a script tag or the runtime environment. Global augmentation must be done carefully to avoid polluting the global namespace.
Example
// express-extension.d.ts — augment Express Request
import "express";
declare module "express-serve-static-core" {
    interface Request {
        user?: { id: number; email: string; role: string };
        requestId: string;
    }
}

// Now inside a middleware or route handler:
// req.user?.email  — TypeScript knows about user

// global.d.ts — augment global Window
declare global {
    interface Window {
        __APP_VERSION__: string;
        __FEATURE_FLAGS__: Record<string, boolean>;
    }

    // Augment process.env for Node.js
    namespace NodeJS {
        interface ProcessEnv {
            NODE_ENV: "development" | "production" | "test";
            DATABASE_URL: string;
            JWT_SECRET: string;
            PORT?: string;
        }
    }
}

export {}; // ensures file is treated as a module

// ambient.d.ts — describe a JS library without types
declare module "legacy-utils" {
    export function formatCurrency(
        amount: number,
        currency: string,
        locale?: string
    ): string;

    export function slugify(text: string): string;

    export const VERSION: string;
}

// Using the ambient declaration
import { formatCurrency, slugify } from "legacy-utils";
const price = formatCurrency(19.99, "USD", "en-US");
const slug  = slugify("Hello World"); // "hello-world"