Intersection Types (&)
Intersection Types (&)
Level 5 — Union & Intersection Types A syntax that allows you to combine multiple types into a single, massive type. It essentially means "AND" in the TypeScript type system.
1. Prerequisites
- Union Types (
|) — The exact opposite concept. - Object Types — What Intersection Types are almost exclusively used for.
2. Term Category
TypeScript Core Syntax (Type Intersection Operator): Intersection types (T & U) combine multiple object or contract types into a single unified type containing all merged properties.
3. Explanation
Environment Context
- Compile-Time
(1) Design Motivation — "Why did we design this?"
Sometimes you have two completely separate Object Types, but you need a new object that contains all the properties from both of them combined. Instead of copying and pasting properties, you use an Intersection Type. It forces an object to satisfy Type A AND Type B simultaneously.
(2) The & Syntax
You create an Intersection Type by separating types with the ampersand & character.
interface ErrorHandling {
success: boolean;
error?: string;
}
interface ArtworksData {
artworks: { title: string }[];
}
// Combine them using `&`
type ArtworksResponse = ArtworksData & ErrorHandling;
// This object MUST have properties from BOTH interfaces
const response: ArtworksResponse = {
success: true,
artworks: [{ title: "Mona Lisa" }]
};
(3) Intersection vs Extends
Intersection Types (A & B) achieve a very similar outcome to Interface Inheritance (interface A extends B).
However, Intersections are usually used with type aliases, and they handle conflicting properties slightly differently (Intersections merge conflicting properties into unions/never, while extends throws an error).
4. Common Mistakes & Pitfalls
Mistake 1: Intersecting Primitives
The mistake: A developer writes: type Impossible = string & number;
Why it's wrong: What value is simultaneously a string AND a number? None. It is mathematically impossible.
If you try to intersect primitive types that have no overlap, TypeScript will silently resolve the resulting type to never. You will never be able to assign a value to it.
Golden Rule: Almost exclusively use Intersection Types (&) to combine Object shapes, never primitives. If you are dealing with primitives, you almost certainly want a Union (|).
Mistake 2: Intersecting Incompatible Primitive Types Resulting in never
The mistake: Creating type Bad = string & number; expecting a combined primitive type.
Why it's wrong: No single runtime value can simultaneously be both a string AND a number. Intersecting primitive types evaluates to never.
Incorrect:
type Impossible = string & number; // Evaluates to type 'never'!
Fix:
type Acceptable = string | number; // Use Union type for either string OR number
Mistake 3: Confusing Structural Intersections with Class Inheritance
The mistake: Intersecting objects with conflicting non-optional property types.
Why it's wrong: Intersecting { a: string } & { a: number } merges property a to string & number (never), rendering the entire object un-instantiable.
Incorrect:
type A = { id: string };
type B = { id: number };
type AB = A & B; // AB.id is 'never'!
Fix:
type A = { id: string };
type B = { id: string; extra: number };
type AB = A & B; // Compatible property types merge safely
5. Practice Exercises
Exercise 1: Merging Multiple Object Types with &
Scenario:
Combine a base Timestamps object type with a User type using an intersection User & Timestamps.
Requirements:
- Create
Timestampstype (createdAt,updatedAt). - Create
UserWithTimestampsusing&.
Answer
Implementation
type Timestamps = {
createdAt: Date;
updatedAt: Date;
};
type User = {
id: string;
name: string;
};
type UserRecord = User & Timestamps;
const record: UserRecord = {
id: "usr_100",
name: "Alice",
createdAt: new Date(),
updatedAt: new Date()
};
Technical Explanation
- Intersection types (
T & U) construct a type containing ALL properties from both constituent types. UserRecordrequires all properties fromUserANDTimestamps.- Idiomatic method for composing object shapes without interface inheritance.
Exercise 2: Auditing Impossible Primitive Intersections
Scenario:
Demonstrate what happens when intersecting incompatible primitive types like string & number.
Requirements:
- Show why
string & numberevaluates tonever.
Answer
Implementation
type Impossible = string & number; // Evaluates to 'never'
// ❌ Compile Error: Type 'string' is not assignable to type 'never'.
// const val: Impossible = "test";
Technical Explanation
- Primitive types are disjoint sets; no single value can be simultaneously a
stringAND anumber. - Intersecting disjoint primitive types evaluates automatically to
never. - Signals an impossible type contract to the compiler.
Exercise 3: Comparative Analysis: Intersections (&) vs Unions (|)
Scenario:
Formulate an architectural comparison matrix contrasting Type Intersections (&) against Type Unions (|).
Requirements:
- Contrast logical operations (AND vs OR), property accessibility, and assignability rules.
Answer
Implementation
Intersection (&) vs Union (|) Matrix:
- Intersection (T & U): Logical AND. Object must possess ALL properties of T AND U. Accessing any property from T or U is allowed.
- Union (T | U): Logical OR. Object can be of type T OR U. Only properties COMMON to both T and U can be accessed without type narrowing.
Technical Explanation
- Intersections combine properties, broadening property accessibility.
- Unions combine candidate types, restricting direct property access to common members.
- Core set theory operations in TypeScript's type system.
6. Related Terms
- Union Types (
|) — The OR operator. - Interfaces — The alternative way to combine object shapes (using
extends). - Branded / Nominal Types — Related concept: Branded / Nominal Types.
7. Key Takeaways
- Intersection Types use the
&(ampersand) operator to combine multiple types together (Type A AND Type B). - The resulting type must possess all properties from all intersected types.
- It is primarily used to merge Object Types or Interfaces together.
- Intersecting mutually exclusive primitives (like
string & number) results in thenevertype.