Intersection types in TypeScript allow you to create composite types that combine the properties and methods of all original types. This is a powerful tool for building flexible and extensible data structures without excessive class inheritance. The construction is implemented using the & operator between types.
TypeScript has supported union types (|) since its early versions to express "or", but there is often a need to describe an object with multiple properties from different independent interfaces or types. This is where intersection (&) is used — the object must satisfy all interfaces for all properties.
One of the main difficulties is the conflict of identical property names in intersecting types, the difference in their typing, as well as the correctness of the resulting combined type when merging classes with private or protected fields. It is also common to confuse intersection types with union types, which can lead to non-obvious compilation errors or issues with object usage.
Intersection types aggregate all properties from the merging types, and for each property, compliance with both types is required if the names match. It can be used for both interfaces and type aliases.
interface A { foo: string; } interface B { bar: number; } type AB = A & B; const item: AB = { foo: "hello", bar: 123 }; // Correct
If properties with the same name intersect, the type must match; otherwise, an error occurs:
interface X { val: string; } interface Y { val: number; } // type Z = X & Y; // Error: incompatible val
Key features:
& operator combines all properties of both types (interfaces and type aliases).What happens if types intersect, and some properties have incompatible types? (For example, one property is string, the other is number)
There will be a compilation error because a property cannot be both string and number simultaneously.
Is it possible to intersect classes with private or protected properties?
Yes, but if such fields have identical names and different access types, the result will be invalid, and TypeScript will raise an error.
How does intersection type differ from union type (|)?
Intersection (A & B) requires the object to be of both types at the same time, while union (A | B) requires it to be at least one of them. For example:
type U = A | B; // Can be foo or bar or both type I = A & B; // Must be both properties
A developer creates a type through the intersection of several inconsistent interfaces; properties conflict, leading to hard-to-debug type errors.
Pros: The ability to quickly combine the capabilities of several types.
Cons: The code does not compile or contains implicit bugs; debugging is hard.
Separation of functionalities into independent interfaces and careful combination through intersection types to form final composite objects.
Pros: Scalability, ease of testing and extension, strict contract.
Cons: Additional work on designing interfaces and aligning them.