What is the difference between union and intersection types in TypeScript?
A union type (A | B) means a value can be one of several types, so you can only use what they have in common until you narrow it. An intersection type (A & B) means a value must be all of the types at once, so it has every property from each.
Explain it simply
Think of a college form that says "Submit Aadhaar or PAN as ID proof." Either document is fine. That is a union: one of these.
Now think of a job form that says "You must be a graduate and have a driving licence." You need both. That is an intersection: all of these at once.
The surprising part is what you can do with each:
- With a union, TypeScript does not know which one you have, so it only lets you use what both share, until you check.
- With an intersection, the value has everything from both, so you can use all of it.
Example
// Union: one of several types
type Id = string | number;
function printId(id: Id): void {
// id.toUpperCase(); // Error: number has no toUpperCase
console.log(id.toString()); // OK: both have toString
if (typeof id === "string") {
console.log(id.toUpperCase()); // OK after narrowing
}
}
// Union of literal types: a fixed set of values
type Size = "small" | "medium" | "large";
// Intersection: combine object types
type Person = { name: string; email: string };
type Employee = { employeeId: number; department: string };
type Staff = Person & Employee;
const s: Staff = {
name: "Priya",
email: "priya@example.com",
employeeId: 1042,
department: "Finance",
}; // must have all four properties
// Intersection of incompatible types becomes never
type Impossible = string & number; // neverHow it works
It helps to think of types as sets of values.
string | numberis the set of all strings plus all numbers: a bigger set. A bigger set means fewer guarantees, so fewer operations are safe.Person & Employeeis the set of values that are both a Person and an Employee: a smaller set. A smaller set means more guarantees, so more properties are available.
This is why the names can feel backwards for objects. A union of two object types gives you fewer usable properties (only the common ones), while an intersection gives you more properties (all of them).
If two intersected object types share a property with conflicting types, like { id: string } & { id: number }, that property becomes never, so no real value can satisfy it.
Real-world use
- Unions: function parameters that accept several types, string literal sets for button variants or order status, and nullable values like
User | null. - Discriminated unions: API states such as
{ status: "loading" } | { status: "success"; data: Product[] }. - Intersections: adding fields to an existing type, like
type WithTimestamps<T> = T & { createdAt: Date }, or combining props in React:ButtonProps & { icon: string }.
Common mistakes
- Expecting to access a property that exists on only one member of a union without narrowing first.
- Thinking
A | Bfor objects means "has all fields of A and B". That isA & B. - Intersecting types with conflicting properties and getting
neverwithout noticing until assignment fails. - Using intersections where
interface extendswould give clearer error messages.extendsreports conflicting properties directly; intersections quietly producenever.
What to say in the interview
"A union, written A | B, means the value is one of the types, so TypeScript only lets me use members common to all of them until I narrow with typeof, in or a discriminant field. An intersection, written A & B, means the value is all of the types at once, so it has every property from each. If I think of types as sets, a union is a bigger set with fewer guarantees, and an intersection is a smaller set with more guarantees. I use unions for alternatives like API states and intersections to combine object types, and I remember that incompatible intersections like string & number become never."
Follow-up questions
- What is a discriminated union?
- What happens when you intersect two object types with the same property but different types?
- When would you use interface extends instead of an intersection?
- What is the type of
keyof (A | B)compared withkeyof (A & B)?
Go deeper
Read these once the basics above feel easy.
For keys, the set view flips again: keyof (A | B) gives only the keys common to both, while keyof (A & B) gives the keys of either (the union of their keys). Also, assigning an object literal to a union type is checked against each member: an object with extra properties that belong to another member of the union is often accepted, because excess property checks look at the union as a whole. Discriminated unions avoid this looseness.