Back to roadmaps typescript Course

Union and Intersection Types

TypeScript allows you to compose complex types from simpler ones. The two primary operators for type composition are the Union (logical OR) and Intersection (logical AND) operators.


1. Union Types

A union type describes a value that can be one of several types. We use the vertical bar (|) to separate each type.

function formatId(id: string | number) {
  // TypeScript only allows actions that are safe for both string and number
  console.log(`The ID is: ${id}`);
}

The Common Properties Rule

If a value has a union type, you can only access properties that are common to all types in the union.

interface Car {
  drive: () => void;
  refuel: () => void;
}

interface ElectricCar {
  drive: () => void;
  charge: () => void;
}

function operateVehicle(vehicle: Car | ElectricCar) {
  vehicle.drive(); // OK - present in both
  // vehicle.charge(); // Error: Property 'charge' does not exist on type 'Car'.
}

2. Intersection Types

An intersection type combines multiple types into one. This new type contains all the properties of all the intersected types. We use the ampersand (&) to merge types.

interface PersonalDetails {
  name: string;
  age: number;
}

interface ProfessionalDetails {
  jobTitle: string;
  salary: number;
}

// StaffMember contains all four properties
type StaffMember = PersonalDetails & ProfessionalDetails;

const employee: StaffMember = {
  name: "John Doe",
  age: 34,
  jobTitle: "Software Engineer",
  salary: 85000
};

3. Resolving Property Conflicts

When intersecting types, you might run into situations where the same property name exists in multiple interfaces but has different types.

Non-overlapping Types

If you try to intersect properties with incompatible types (like string and number), TypeScript resolves that property type to never.

interface TypeA {
  id: string;
}

interface TypeB {
  id: number;
}

type ConflictedType = TypeA & TypeB;

// This will fail compile checks because no value can be both string and number
// const item: ConflictedType = { id: "10" };

4. Summary

  • Use Union types (|) to represent a value that can be one of several different types.
  • Only properties common to all members of a Union can be accessed directly.
  • Use Intersection types (&) to combine multiple type definitions into a single, comprehensive type.
  • Intersecting conflicting primitive types results in a type of never.
Published on Last updated: