Unions vs Intersections in TypeScript
This article explores the concepts of unions and intersections in TypeScript, drawing parallels with set theory. It highlights the differences between union types, which allow for flexibility in object properties, and intersection types, which require all specified properties to be present. Through detailed explanations and examples, this document aims to clarify common misconceptions and provide a deeper understanding of how these types function within TypeScript.
Union Types
Union types in TypeScript enable flexibility in object properties. An object can be assigned either a name object or an age object, or both.
Example:
type Person = { name: string } | { age: number };
Behavior
An object can be either a name an age, or both. This flexibility is due to TypeScript’s structural typing, which allows for compatibility.
Example Assignments:
const person1: Person = { name: "Alice" };
const person2: Person = { age: 30 };
const person3: Person = { name: "Alice", age: 30 }; // This is valid due to structural typing.
Intersection Types
Intersection types require that an object must contain properties from both types. This means that an object must support both name and age properties.
Example:
type Person = { name: string } & { age: number };
Behavior
An object must contain both properties. If you try to assign an object with only one of the properties, TypeScript will throw an error.
Example Assignment:
const person: Person = { name: "Alice", age: 30 }; // This is valid.
Attempting to assign:
const personInvalid1: Person = { name: "Alice" }; // Compile-time error.
const personInvalid2: Person = { age: 30 }; // Compile-time error.
Common Misconceptions
A common misunderstanding is that union types can safely handle objects with both properties. This is not the intended use case for unions, and relying on this can lead to errors.
Thought Experiment
Consider how to make unions fully support cases where both values are provided without causing errors. This reflects the need for a clear understanding of TypeScript’s type system and its structural typing.