Intersections and Composition
Combine multiple types into a single, powerful structure using intersection types and learn when to reach for this advanced composition tool.
From “either/or” to “both/and”
We’ve already seen how to model choices in TypeScript using union types. But in real-world systems, we often need to model combinations—types that require multiple capabilities or concerns to come together.
Interfaces gave us one way to do this: with extends
, we can inherit from a single base shape. But when we want to combine anything—multiple interfaces, type aliases, or inline types—we need a more flexible tool.
That tool is the intersection type, written with &
. It is TypeScript’s way of saying: “This value must be everything these types require.”
Declaring an intersection type
An intersection type lets us build a new type that satisfies all the members of multiple types at once. The syntax TypeA & TypeB
creates a new type that must match every member in the list. Think of it as logical and at the type level.
{"compilerOptions": {"target": "ES2020","module": "commonjs","strict": true}}
Explanation:
Lines 1–2: We define two separate object shapes.
Line 4:
FullUser
merges both. Now any object of this type must haveid
,name
,canEdit
, andcanDelete
.Lines 6–11: A compliant object must satisfy every field; omit one and the compiler shuts us down.
Intersections vs. extends: What’s the difference?
Here’s a quick refresher: Interfaces support extends
for inheritance.
interface AdminUser extends User {isSuperAdmin: boolean;}
We can achieve the same result plus more flexibility with an intersection:
type AdminUser = User & { isSuperAdmin: boolean };
The key difference is that extends
only ...