0
0
Typescriptprogramming~15 mins

Intersection type syntax in Typescript - Deep Dive

Choose your learning style9 modes available
Overview - Intersection type syntax
What is it?
Intersection types in TypeScript let you combine multiple types into one. This means a value must satisfy all the combined types at once. It helps create more precise and flexible type definitions by merging properties and behaviors from different types.
Why it matters
Without intersection types, you would struggle to express that something needs to meet multiple type requirements simultaneously. This would make your code less safe and harder to understand. Intersection types help catch errors early and make your programs clearer and more reliable.
Where it fits
Before learning intersection types, you should understand basic TypeScript types and interfaces. After mastering intersections, you can explore union types, type guards, and advanced type manipulations like mapped types and conditional types.
Mental Model
Core Idea
An intersection type means a value must have all the features of every combined type at the same time.
Think of it like...
It's like wearing multiple hats stacked on your head—you must wear all of them together to be allowed in a special club.
TypeA ─┐
         ├─ IntersectionType (TypeA & TypeB)
TypeB ─┘

Value must satisfy both TypeA and TypeB properties.
Build-Up - 6 Steps
1
FoundationBasic type combination concept
🤔
Concept: Learn what it means to combine types so a value fits multiple shapes.
In TypeScript, you can combine types using the & symbol. For example, type A = {name: string}; type B = {age: number}; type C = A & B; means C must have both name and age properties.
Result
A value of type C must have both a name (string) and an age (number).
Understanding that & merges types helps you create more detailed and accurate type definitions.
2
FoundationDifference from union types
🤔
Concept: Distinguish intersection (&) from union (|) types.
Union types mean a value can be one type or another (A | B). Intersection types mean a value must be both types at once (A & B). For example, {name: string} | {age: number} accepts either, but {name: string} & {age: number} requires both.
Result
Intersection types are stricter, requiring all combined properties.
Knowing the difference prevents confusion and helps you choose the right type for your needs.
3
IntermediateCombining interfaces with intersections
🤔Before reading on: do you think intersection types create a new type with properties from both interfaces or just one of them? Commit to your answer.
Concept: Intersection types merge multiple interfaces into one type with all their properties.
interface A {name: string;} interface B {age: number;} type C = A & B; Now, C requires both name and age. This is useful when you want to combine behaviors or data from different sources.
Result
Type C has both name and age properties required.
Understanding this merging helps you design flexible and reusable type structures.
4
IntermediateUsing intersections with primitive and object types
🤔Before reading on: can intersection types combine primitive types like string & number? Commit to your answer.
Concept: Intersection types can combine object types but combining incompatible primitives results in never type.
type A = {name: string}; type B = {age: number}; type C = A & B; // valid // But type D = string & number; // results in never because no value can be both string and number.
Result
Intersection of incompatible primitives is never; intersection of objects merges properties.
Knowing this prevents type errors and helps you use intersections correctly.
5
AdvancedIntersection types with functions and overloads
🤔Before reading on: do you think intersecting function types creates a function that must satisfy all signatures or just one? Commit to your answer.
Concept: Intersection of function types means the function must satisfy all combined call signatures.
type FuncA = (x: number) => string; type FuncB = (y: string) => number; type FuncC = FuncA & FuncB; A function of type FuncC must accept both a number and a string and return the correct type accordingly, effectively combining overloads.
Result
FuncC behaves like a function with multiple call signatures.
Understanding this allows you to create complex function types with multiple behaviors.
6
ExpertIntersection types and type inference surprises
🤔Before reading on: do you think TypeScript always infers intersection types as expected when combining generics? Commit to your answer.
Concept: TypeScript sometimes infers intersection types in unexpected ways, especially with generics and conditional types.
When using generics, intersections can cause inference to pick narrower or broader types than expected. For example, combining generic constraints with intersections may lead to unexpected assignability or excess property checks.
Result
Type inference with intersections can be tricky and may require explicit annotations.
Knowing these quirks helps avoid subtle bugs and write more predictable generic code.
Under the Hood
At runtime, TypeScript types do not exist; they are erased. Intersection types are a compile-time construct that instructs the compiler to check that values satisfy all combined types. The compiler merges properties and call signatures from each type into one composite type. If conflicts arise, it reports errors. This merging happens structurally, meaning the shape of the value matters, not its name.
Why designed this way?
Intersection types were introduced to allow more precise type modeling without runtime overhead. They enable combining multiple behaviors or data shapes safely. Alternatives like inheritance or union types either lack flexibility or express different concepts. Structural typing and intersections fit TypeScript's goal of gradual typing over JavaScript's dynamic nature.
┌─────────────┐     ┌─────────────┐
│  Type A    │     │  Type B    │
│ name: str  │     │ age: num   │
└─────┬──────┘     └─────┬──────┘
      │                  │
      └─────┬────────────┘
            │
    ┌───────▼────────┐
    │ Intersection   │
    │ Type A & B     │
    │ name: str      │
    │ age: num       │
    └────────────────┘
Myth Busters - 3 Common Misconceptions
Quick: Does an intersection type mean a value can be either type A or type B? Commit to yes or no.
Common Belief:Intersection types mean a value can be one type or the other, like a union.
Tap to reveal reality
Reality:Intersection types require the value to satisfy all types simultaneously, not just one.
Why it matters:Confusing intersection with union leads to incorrect assumptions about what values are allowed, causing type errors or runtime bugs.
Quick: Can you intersect two primitive types like string & number and get a useful type? Commit to yes or no.
Common Belief:You can combine any types with &, including primitives, to get a new type.
Tap to reveal reality
Reality:Intersecting incompatible primitives results in the never type, meaning no value can satisfy it.
Why it matters:Trying to intersect incompatible primitives wastes time and causes confusing errors.
Quick: Does TypeScript always infer intersection types correctly when used with generics? Commit to yes or no.
Common Belief:TypeScript's type inference perfectly handles intersections in all cases.
Tap to reveal reality
Reality:Type inference with intersections can be surprising and sometimes requires explicit hints.
Why it matters:Assuming perfect inference can cause subtle bugs and frustration when types don't behave as expected.
Expert Zone
1
Intersection types merge properties structurally, so overlapping properties must be compatible or cause errors.
2
When intersecting function types, the resulting type behaves like a function with multiple overloads, which can be tricky to implement.
3
Intersections with generics can cause inference to pick unexpected types, requiring explicit annotations or helper types.
When NOT to use
Avoid intersection types when you want a value to be one of several types (use union types instead). Also, do not use intersections to combine incompatible primitives or unrelated types, as this leads to never types or confusing errors.
Production Patterns
In real-world TypeScript projects, intersection types are used to combine multiple interfaces for complex objects, merge props in React components, create flexible utility types, and define functions with multiple call signatures. They help enforce strict contracts while keeping code reusable.
Connections
Set theory
Intersection types correspond to the intersection operation in set theory, where an element must belong to all sets.
Understanding set intersections clarifies why intersection types require all combined properties simultaneously.
Multiple inheritance in OOP
Intersection types mimic multiple inheritance by combining features from multiple types into one.
Knowing multiple inheritance helps understand how intersection types merge behaviors without runtime complexity.
Logical AND in Boolean algebra
Intersection types behave like logical AND, requiring all conditions to be true.
This connection helps grasp why all type constraints must be met for intersection types.
Common Pitfalls
#1Trying to use intersection types as unions.
Wrong approach:type A = {name: string}; type B = {age: number}; type C = A & B; // expecting C to accept either name or age only const person: C = {name: 'Alice'}; // Error: missing age
Correct approach:type C = A | B; // union type const person: C = {name: 'Alice'}; // valid const person2: C = {age: 30}; // valid
Root cause:Confusing intersection (&) with union (|) leads to wrong expectations about allowed values.
#2Intersecting incompatible primitive types.
Wrong approach:type A = string & number; const value: A = 'hello'; // Error: Type 'string' is not assignable to never
Correct approach:Use union if you want either type: type A = string | number; const value: A = 'hello'; // valid const value2: A = 42; // valid
Root cause:Misunderstanding that primitives cannot be intersected meaningfully.
#3Assuming TypeScript infers intersection types perfectly with generics.
Wrong approach:function combine(a: T, b: U): T & U { return {...a, ...b}; } const result = combine({x: 1}, {y: 'a'}); // TypeScript may infer unexpected types or lose some info
Correct approach:Add explicit type annotations or constraints: function combine(a: T, b: U): T & U { return {...a, ...b}; } const result = combine({x: 1}, {y: 'a'});
Root cause:Overreliance on inference without constraints causes unexpected type results.
Key Takeaways
Intersection types combine multiple types into one that requires all properties and behaviors simultaneously.
They differ from union types, which allow a value to be one type or another, not both.
Intersection types work structurally by merging properties and call signatures, enabling flexible and precise type definitions.
They cannot meaningfully combine incompatible primitive types, which results in the never type.
Understanding intersection types deeply helps write safer, clearer, and more reusable TypeScript code.