ProgrammingFullstack Developer

Describe the mechanism of intersection types in TypeScript. How can combined types be implemented using them, what is the difference from union types, and what are the main nuances in inheritance and property compatibility?

Pass interviews with Hintsage AI assistant

Answer.

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.

Background

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.

Problem

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.

Solution

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:

  • The & operator combines all properties of both types (interfaces and type aliases).
  • If a property exists in both types, the resulting type is their intersection (it must comply with both).
  • It is used for flexibly combining functionality without creating new classes or hierarchies.

Trick questions.

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

Typing errors and anti-patterns

  • Intersection of incompatible types or conflicting properties with different types will lead to errors.
  • Misusing intersection to circumvent strict typing makes the code confusing.

Real-life example

Negative case

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.

Positive case

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.