Merge and Nest: Merge Strategies for Multiple Interfaces with Examples
In TypeScript, interfaces are used to define the structure of objects, and interface merging and nesting are key techniques for implementing complex object structures. Interface merging refers to integrating the properties and methods of multiple interfaces, while nesting refers to one interface containing the definition of another. These two techniques are commonly used to build flexible and maintainable code architectures.
Merge Strategies
Shallow Merge
A shallow merge simply combines the properties and methods of multiple interfaces without considering nested relationships. For example, when two interfaces A and B have conflicting properties, a shallow merge retains the latest property value.
interface A {
name: string;
age: number;
}
interface B {
age: number;
city: string;
}
// Shallow merge
type Combined = A & B;
const obj: Combined = { name: "Alice", age: 30, city: "New York" };
Deep Merge
A deep merge takes the nested structure of interfaces into account, merging nested properties and processing them recursively. For example, if interface A contains the definition of interface B, a deep merge will merge B's properties into A.
interface A {
name: string;
age: number;
// Nested interface B
b: B;
}
interface B {
city: string;
country: string;
}
// Deep merge
type Combined = A & B;
const obj: Combined = {
name: "Alice",
age: 30,
b: { city: "New York", country: "USA" }
};
Dynamic Merge
Dynamic merge allows deciding whether to merge certain properties based on runtime conditions. For example, if a property is marked as "optional," dynamic merge will ignore the value of that property.
interface A {
name: string;
age: number;
}
interface B {
age: number;
isOptional: boolean;
}
// Dynamic merge
type Combined = A & (B extends { isOptional: true } ? B : {});
const obj: Combined = { name: "Alice", age: 30, isOptional: true };
Nested Structures
Interface nesting refers to one interface containing the definition of another. This structure is commonly used to build clearly hierarchical class structures, such as a user object containing an address object.
interface Address {
street: string;
city: string;
}
interface User {
name: string;
age: number;
address: Address;
}
// Nested structure
const user: User = {
name: "Alice",
age: 30,
address: { street: "123 Main St", city: "New York" }
};
Illustrative Examples
Scenario of Multiple Interface Merging
When multiple interfaces need to share certain properties, they can be merged to achieve a unified interface definition. For example, a project may have multiple modules, each with its own interface, but sharing certain common properties.
interface Module1 {
moduleName: string;
version: string;
}
interface Module2 {
moduleName: string;
version: string;
features: string[];
}
// Merged interface
type Combined = Module1 & Module2;
const module: Combined = { moduleName: "Module A", version: "1.0", features: ["Feature 1"] };
Scenario of Interface Nesting
Nested interfaces are commonly used to build complex objects, such as an order object containing customer information and payment information.
interface Customer {
name: string;
email: string;
}
interface Payment {
amount: number;
status: "PAID" | "UNPAID";
}
interface Order {
customer: Customer;
payment: Payment;
}
// Nested structure
const order: Order = {
customer: { name: "Alice", email: "alice@example.com" },
payment: { amount: 100, status: "PAID" }
};
Summary
Interface merging and nesting are important means for implementing complex object structures in TypeScript. By using shallow merge, deep merge, and dynamic merge, developers can flexibly manage interface properties and methods. Nested interfaces help build clearly hierarchical class structures, improving code maintainability. Reasonably applying these techniques can significantly enhance code readability and extensibility.