0
0
Typescriptprogramming~15 mins

Union vs intersection mental model in Typescript - Trade-offs & Expert Analysis

Choose your learning style9 modes available
Overview - Union vs intersection mental model
What is it?
Union and intersection are ways to combine types in TypeScript. A union type means a value can be one of several types. An intersection type means a value must have all the combined types at once. These help describe what kind of data your program can accept or produce.
Why it matters
Without union and intersection types, programs would be less flexible or safe. Union types let you accept multiple kinds of inputs without losing type safety. Intersection types let you combine features from different types to create richer objects. Without them, code would be more error-prone and harder to understand.
Where it fits
Learners should know basic TypeScript types and how to declare them. After this, they can learn about advanced type features like type guards, mapped types, and conditional types to write safer and more expressive code.
Mental Model
Core Idea
Union means 'one or the other', intersection means 'both at the same time'.
Think of it like...
Imagine a box of crayons: a union is like choosing one crayon from a box of different colors, while an intersection is like having a crayon that is both red and blue painted together.
Types combined:

  Union (A | B):
  ┌─────┐   ┌─────┐
  │  A  │ OR│  B  │
  └─────┘   └─────┘
  Result: A or B

  Intersection (A & B):
  ┌─────┐   ┌─────┐
  │  A  │AND│  B  │
  └─────┘   └─────┘
  Result: A and B combined
Build-Up - 7 Steps
1
FoundationUnderstanding basic union types
🤔
Concept: Union types allow a value to be one of several types.
In TypeScript, you can write a type like `string | number` which means the value can be a string or a number. For example: const value: string | number = 'hello'; const anotherValue: string | number = 42; This means the variable can hold either type safely.
Result
Variables can hold values of multiple types, increasing flexibility.
Knowing union types lets you accept different kinds of inputs without losing type safety.
2
FoundationUnderstanding basic intersection types
🤔
Concept: Intersection types combine multiple types into one that has all properties.
An intersection type like `A & B` means the value must satisfy both types A and B. For example: interface A { name: string; } interface B { age: number; } const person: A & B = { name: 'Alice', age: 30 }; The object must have both name and age properties.
Result
Values must have all combined properties, creating richer types.
Intersection types let you build complex types by combining simpler ones.
3
IntermediateHow unions affect type checking
🤔Before reading on: do you think you can access properties common to all union types without checks? Commit to your answer.
Concept: When using union types, you can only safely access members common to all types unless you check the type first.
For example, with `string | number`, you cannot call `.toFixed()` directly because only numbers have it. You must check the type first: function format(value: string | number) { if (typeof value === 'number') { return value.toFixed(2); } else { return value.toUpperCase(); } } This prevents runtime errors.
Result
TypeScript forces you to check types before using specific properties.
Understanding this prevents common bugs when working with union types.
4
IntermediateHow intersections combine properties
🤔Before reading on: do you think intersection types merge properties or override them? Commit to your answer.
Concept: Intersection types merge properties from all combined types, requiring values to have all of them.
If two interfaces have different properties, the intersection requires both: interface A { x: number; } interface B { y: string; } const point: A & B = { x: 10, y: 'left' }; If properties overlap with the same name and type, they must match exactly.
Result
Intersection types create new types with combined features.
Knowing how intersections merge properties helps design precise types.
5
IntermediateUsing unions and intersections with functions
🤔Before reading on: do you think a function parameter typed as a union accepts all combined types or only one? Commit to your answer.
Concept: Functions can accept union or intersection types to handle flexible inputs or require combined features.
Example with union: function printId(id: number | string) { console.log('ID:', id); } Example with intersection: interface HasName { name: string; } interface HasAge { age: number; } function printPerson(person: HasName & HasAge) { console.log(`${person.name} is ${person.age} years old.`); } Unions allow multiple input types; intersections require all features.
Result
Functions become more flexible or more strict depending on type usage.
Understanding this helps write safer and clearer function interfaces.
6
AdvancedComplex types: unions of intersections and vice versa
🤔Before reading on: do you think unions and intersections can be nested arbitrarily? Commit to your answer.
Concept: You can combine unions and intersections in complex ways to model real-world data precisely.
Example: type A = { a: number }; type B = { b: string }; type C = { c: boolean }; type UnionOfIntersections = (A & B) | (B & C); This means a value is either both A and B, or both B and C. This models choices with shared parts. TypeScript checks these carefully to ensure correctness.
Result
You can express very detailed type rules for complex data.
Mastering nested unions and intersections unlocks powerful type modeling.
7
ExpertTypeScript type inference with unions and intersections
🤔Before reading on: do you think TypeScript always infers unions or intersections correctly without hints? Commit to your answer.
Concept: TypeScript uses complex inference rules to decide when to infer unions or intersections, but sometimes needs help with type annotations or assertions.
For example, when combining types in generics or conditional types, inference can produce unexpected unions or intersections. function merge(a: T, b: U): T & U { return { ...a, ...b }; } Here, TypeScript infers the return as intersection of T and U. But inference can fail or produce overly broad types, requiring explicit annotations. Understanding inference internals helps debug tricky type errors.
Result
You can write more precise and maintainable code by guiding inference.
Knowing inference limits prevents confusing errors and improves developer experience.
Under the Hood
TypeScript represents union types as a set of possible types and intersection types as a combination of all properties from each type. At compile time, it checks that values conform to these rules. Unions allow any one type from the set, while intersections require all combined properties to exist. The compiler uses control flow analysis to narrow union types based on runtime checks.
Why designed this way?
Unions and intersections were designed to balance flexibility and safety. Unions let developers accept multiple types without losing type checking, while intersections let them compose complex types from simpler ones. This design avoids the pitfalls of untyped languages and overly rigid type systems, enabling gradual typing and expressive code.
TypeScript Type Combination

  ┌─────────────┐
  │   Union     │
  │  (A | B)    │
  └─────┬───────┘
        │
  Accepts any one type

  ┌─────────────┐
  │ Intersection│
  │  (A & B)    │
  └─────┬───────┘
        │
  Requires all types combined

Compiler checks values against these rules during type checking.
Myth Busters - 4 Common Misconceptions
Quick: Does a union type mean a value must have all properties from all types? Commit to yes or no.
Common Belief:A union type means the value has all properties from all types combined.
Tap to reveal reality
Reality:A union type means the value can be any one of the types, not all at once.
Why it matters:Believing this causes confusion and incorrect assumptions about what properties are safe to access, leading to runtime errors.
Quick: Can intersection types combine conflicting property types without error? Commit to yes or no.
Common Belief:Intersection types can combine properties with the same name but different types without issues.
Tap to reveal reality
Reality:If properties conflict in type, the intersection becomes impossible to satisfy, causing type errors.
Why it matters:Ignoring this leads to impossible types and confusing compiler errors.
Quick: Does TypeScript automatically narrow union types without explicit checks? Commit to yes or no.
Common Belief:TypeScript always knows which union type a value is without programmer help.
Tap to reveal reality
Reality:TypeScript requires explicit type checks or type guards to narrow union types safely.
Why it matters:Assuming automatic narrowing causes unsafe property access and bugs.
Quick: Are union and intersection types just syntactic sugar with no real difference? Commit to yes or no.
Common Belief:Union and intersection types are just different ways to write the same thing.
Tap to reveal reality
Reality:They represent fundamentally different concepts: choice versus combination.
Why it matters:Confusing them leads to wrong type designs and misunderstandings of code behavior.
Expert Zone
1
Intersection types distribute over unions in complex ways, affecting how types combine and infer.
2
Excess property checks behave differently with unions and intersections, impacting object literals.
3
TypeScript's control flow analysis narrows union types but cannot narrow intersections, influencing type guard design.
When NOT to use
Avoid unions when you need guaranteed properties on values; use intersections instead. Avoid intersections when values can only be one type at a time; use unions. For very dynamic data, consider unknown or any types with runtime checks instead.
Production Patterns
Unions are often used for function parameters accepting multiple input types or API responses with variant shapes. Intersections are used to compose mixins, add features to objects, or combine multiple interfaces for complex data models.
Connections
Set theory
Union and intersection types correspond to set union and intersection operations.
Understanding set theory helps grasp how types combine and overlap in programming.
Database queries
Union types are like SQL UNION (combine rows), intersections like JOIN (combine columns).
This analogy clarifies how data shapes merge or choose between alternatives.
Logic gates
Union is like OR gate (one or the other), intersection like AND gate (both required).
Knowing logic gates helps understand how conditions combine in types.
Common Pitfalls
#1Accessing properties of a union type without type checks.
Wrong approach:function printLength(value: string | number) { console.log(value.length); }
Correct approach:function printLength(value: string | number) { if (typeof value === 'string') { console.log(value.length); } else { console.log('No length for number'); } }
Root cause:Misunderstanding that union types require narrowing before accessing specific properties.
#2Creating an intersection type with conflicting property types.
Wrong approach:type Conflicting = { x: number } & { x: string };
Correct approach:Use compatible property types or rename properties to avoid conflict: type Compatible = { x: number } & { y: string };
Root cause:Not realizing intersections require all properties to be compatible and mergeable.
#3Assuming a union type variable can be used as if it has all properties combined.
Wrong approach:function greet(person: { name: string } | { age: number }) { console.log(person.name.toUpperCase()); }
Correct approach:function greet(person: { name: string } | { age: number }) { if ('name' in person) { console.log(person.name.toUpperCase()); } else { console.log('No name available'); } }
Root cause:Confusing union types with intersection types and ignoring type narrowing.
Key Takeaways
Union types represent a value that can be one of several types, requiring type checks before accessing specific properties.
Intersection types combine multiple types into one, requiring values to have all combined properties simultaneously.
TypeScript uses control flow analysis to narrow union types but requires explicit checks to avoid runtime errors.
Understanding the difference between union and intersection types is essential for writing flexible and safe TypeScript code.
Mastering these types enables precise modeling of complex data and function interfaces in real-world applications.