TypeScript merges multiple declarations of the same name.
Interface Merging
interface User {
name: string;
}
interface User {
age: number;
}
// Merged: { name: string; age: number; }
const user: User = {
name: "Alice",
age: 25
};
Merging with Different Property Types
interface Document {
createElement(tagName: "div"): HTMLDivElement;
createElement(tagName: "span"): HTMLSpanElement;
}
interface Document {
createElement(tagName: "a"): HTMLAnchorElement;
}
// All overloads are merged
Namespace Merging
namespace Geometry {
export function area() {
// ...
}
}
namespace Geometry {
export function perimeter() {
// ...
}
}
// Both functions are available
Geometry.area();
Geometry.perimeter();
Class and Interface Merging
class Album {
label: Album.AlbumLabel;
}
namespace Album {
export class AlbumLabel {
// ...
}
}
// Album class has label property of type Album.AlbumLabel
Enum Merging
enum Color {
Red,
Green
}
enum Color {
Blue = 2,
Yellow
}
// Merged enum: Red=0, Green=1, Blue=2, Yellow=3
Module and Namespace Merging
// shapes.ts
export class Triangle {
// ...
}
// augmentation.ts
import { Triangle } from "./shapes";
declare module "./shapes" {
namespace Triangle {
export function create(): Triangle;
}
}
Triangle.create(); // Available after augmentation
Exercises
Exercise 1: Interface Merging
// Create an interface in one file
// Extend it in another file using declaration merging
// Use the merged interface
Exercise 2: Namespace Merging
// Create a namespace with some exports
// Extend it in another file
// Use all merged exports
Exercise 3: Class and Namespace
// Create a class
// Add static methods via namespace merging
// Use both instance and static methods
Exercise 4: Module Augmentation
// Augment a module's exports
// Add new interfaces and types
// Use them in your code
Exercise 5: Complex Merging
// Combine interface, namespace, and module merging
// Create a comprehensive example
Best Practices
- Use for extensibility - When you need to extend types
- Document merges - Explain what's being merged
- Avoid conflicts - Don't create incompatible merges
- Use namespaces - For organizing related types
- Be careful with enums - Enum merging can be confusing
Common Mistakes
- Conflicting property types
// ❌ Error: Property 'x' must be of type 'string'
interface A {
x: string;
}
interface A {
x: number; // Conflict!
}
- Merging non-mergable declarations
// ❌ Can't merge type aliases
type A = string;
type A = number; // Error
- Namespace conflicts
// ❌ Conflicting exports
namespace N {
export const x = 1;
}
namespace N {
export const x = 2; // Error: Duplicate identifier
}
Next Steps
Learn about Branded Types and Opaque Types.