ProgrammingBackend TypeScript Developer

Tell us about the 'intersection types' mechanism in TypeScript. How to use them correctly and what pitfalls can be encountered?

Pass interviews with Hintsage AI assistant

Answer

Intersection types (&, intersection types) allow combining multiple types into one that possesses all the properties of the combined types.

Example:

type Person = { name: string }; type Worker = { job: string }; type WorkingPerson = Person & Worker; // { name: string; job: string } const wp: WorkingPerson = { name: "Leo", job: "Dev" };

This is convenient when composing extensible contracts and building complex types from primitives.

However, if incompatible types intersect (for example, type A = { foo: string } and type B = { foo: number }), the resulting type cannot be initialized.

Example of incorrect intersection:

type A = { foo: string }; type B = { foo: number }; type C = A & B; // C = { foo: never }

Trick question

What happens if you intersect two types with the same field having incompatible data types?

Answer: The field will have the type never, as a value cannot simultaneously be both, a string and a number. Such a type cannot be validly implemented.

type T1 = { id: string }; type T2 = { id: number }; type T3 = T1 & T2; // { id: never }

Examples of real errors due to ignorance of the topic's subtleties


Story

In a project, types from different libraries were intersected without noticing that there were identical fields with different types. As a result, an unexpected "impossible" (never) type was produced, which led to the inability to create a valid object for the API call.


Story

A developer needed to "glue" together DTO types and domain entities. The intersection resulted in two incompatible properties, and trying to use the resulting type led to ambiguous compilation errors. The developer spent time debugging before understanding the cause.


Story

In one of the microservices, an intersected type was declared to describe the request body. Due to an API change, one of the properties received a different type, and the new changes did not immediately result in a compilation error — problems only appeared at runtime after deployment.