Declaration merging is TypeScript combining multiple declarations with the same name into a single definition. Interfaces, namespaces, and some other constructs merge automatically.
Interface merging
interface Box { width: number; }
{ : ; }
Declaration merging is TypeScript combining multiple declarations with the same name into a single definition. Interfaces, namespaces, and some other constructs merge automatically.
interface Box { width: number; }
{ : ; }
This is how you add types to libraries or globals you don't own:
// Add a custom property to Express's Request
declare global {
namespace Express {
interface Request { user?: { id: string }; } // merges into Express.Request
}
}
request.user; // ✅ now typed everywhere
// Augment a module
declare module "some-lib" {
interface Options { newOption: boolean; }
}
Because the library's Request/Options is an interface, your declaration merges into it rather than conflicting — letting you safely extend types you can't edit.
function greet() {}
namespace greet { export const version = "1.0"; }
greet.version; // "1.0" — namespace merged onto the function
type can't do thistype A = { x: number };
type A = { y: number }; // ❌ Error: duplicate identifier
Type aliases are unique; only interfaces (and namespaces) merge — a key reason to use interface for extensible public API shapes.
Declaration merging is the mechanism behind module augmentation — extending Express requests, adding to window, customizing library types, theming systems.
It's essential knowledge for typing real apps where you must adapt types you don't control, without forking them.