Module augmentation lets you add new features to existing modules without changing their original code. It helps you extend or fix modules safely.
Module augmentation syntax in Typescript
declare module "module-name" { // add new types, interfaces, or values here interface ExistingInterface { newProperty: string; } function newFunction(): void; }
Use declare module "module-name" to tell TypeScript you want to add to that module.
Only add new things or extend existing ones; do not redefine completely.
age property to the existing User interface in the my-library module.declare module "my-library" { interface User { age: number; } }
userId property to Express's Request interface.declare module "express" { interface Request { userId?: string; } }
newHelper to the some-package module.declare module "some-package" { function newHelper(): void; }
This program adds a new optional property userRole to Express's Request interface using module augmentation. Then it creates a request object, sets the user role, and prints it.
import { Request } from "express"; declare module "express" { interface Request { userRole?: string; } } function printUserRole(req: Request) { if (req.userRole) { console.log(`User role is: ${req.userRole}`); } else { console.log("User role is not set."); } } const req = {} as Request; req.userRole = "admin"; printUserRole(req);
Module augmentation only works if the module is imported or referenced in your code.
Be careful not to overwrite existing types; always extend them.
Use module augmentation to keep your code compatible with library updates.
Module augmentation lets you add or extend types in existing modules.
Use declare module "module-name" to start augmentation.
It helps customize or fix third-party modules without changing their source.
Practice
module augmentation in TypeScript?Solution
Step 1: Understand module augmentation purpose
Module augmentation allows adding or extending types in existing modules without changing their original code.Step 2: Compare options
Only To add or extend types in an existing module without modifying its original source code correctly describes this purpose. Options A, C, and D describe unrelated actions.Final Answer:
To add or extend types in an existing module without modifying its original source code -> Option CQuick Check:
Module augmentation = extend existing types [OK]
- Thinking it creates new modules
- Confusing augmentation with deleting types
- Assuming it converts JS to TS
"my-library"?Solution
Step 1: Recall correct syntax for module augmentation
The correct syntax usesdeclare module "module-name" { ... }to augment a module.Step 2: Check options
Only declare module "my-library" { /* augmentation here */ } matches this syntax exactly. Others use invalid keywords or order.Final Answer:
declare module "my-library" { /* augmentation here */ } -> Option BQuick Check:
Use declare module "name" for augmentation [OK]
- Using wrong keywords like 'augment' or 'module augment'
- Incorrect order of keywords
- Omitting 'declare'
console.log(myLib.newFunction());?
import * as myLib from "my-library";
declare module "my-library" {
export function newFunction(): string;
}
myLib.newFunction = () => "Hello from augmentation!";
console.log(myLib.newFunction());Solution
Step 1: Understand augmentation effect
The module augmentation adds a new function type declaration to "my-library". Then the function is assigned an implementation.Step 2: Check runtime behavior
CallingmyLib.newFunction()runs the assigned arrow function returning the string "Hello from augmentation!".Final Answer:
"Hello from augmentation!" -> Option AQuick Check:
Augmented function runs and returns string [OK]
- Assuming augmentation adds runtime code automatically
- Expecting TypeError because function was not originally present
- Confusing type declaration with implementation
declare module "utils" {
export interface Config {
timeout: number;
}
}
declare module "utils" {
export interface Config {
retries: number;
}
}
const config: Config = { timeout: 1000, retries: 3 };Solution
Step 1: Check interface merging
Interfaces with the same name in module augmentation merge correctly, so no error there.Step 2: Check usage of Config
The variableconfigusesConfigbut does not import or reference it properly, causing an error.Final Answer:
The variable config is missing import from "utils" -> Option DQuick Check:
Missing import causes error, not interface duplication [OK]
- Thinking interface redeclaration causes error
- Ignoring missing imports
- Assuming module name is invalid
logInfo(message: string): void to the existing Logger class from a third-party module "logger-lib" without modifying its source. Which is the correct way to do this using module augmentation?Solution
Step 1: Use correct module augmentation syntax
Usedeclare module "logger-lib" { interface Logger { ... } }to add method signature.Step 2: Add method implementation to prototype
Assign the method toLogger.prototypeto add runtime behavior without modifying original source.Final Answer:
declare module "logger-lib" { interface Logger { logInfo(message: string): void; } } Logger.prototype.logInfo = function(message) { console.log(message); }; -> Option AQuick Check:
Declare interface then add method to prototype [OK]
- Using 'module' instead of 'declare module'
- Declaring class instead of interface in augmentation
- Forgetting to add method implementation
Ready to prove it?
Pass the test and this pattern moves unknown
