New: We've launched a brand new Coding Challenges section! Check out these interactive, real-world exercises to level up your skills.Explore Challenges
FrontendPrep
typescriptEasy

TypeScript: Union and Intersection Types

Loading...

Learn how union types (|) and intersection types (&) work in TypeScript. Understand how they combine primitive and object types, and how to narrow union types.

Arvind M
Arvind MLinkedIn

TypeScript: Union and Intersection Types

One of the common core questions in a TypeScript interview is:

Explain the differences between Union (|) and Intersection (&) types in TypeScript. How do they behave when applied to primitive types vs. object types?

Unions and intersections allow you to compose complex types out of simpler types. However, their behavior changes depending on whether they are combining primitives (like strings/numbers) or object types (interfaces).


1. Union Types (|)

A union type represents a value that can be one of several types. It is created using the pipe (|) symbol.

type ID = string | number;
 
let userId: ID;
userId = "abc"; // ✅ Allowed
userId = 123;   // ✅ Allowed
userId = true;  // ❌ Compile Error: Type 'boolean' is not assignable to type 'ID'.

Union behavior on Objects:

If you have a union of two object shapes, you can only safely access properties that are common to both types unless you perform type narrowing.

interface Bird {
  fly(): void;
  layEggs(): void;
}
interface Fish {
  swim(): void;
  layEggs(): void;
}
 
function getAnimal(): Bird | Fish { ... }
const pet = getAnimal();
 
pet.layEggs(); // ✅ Allowed (Common to both)
pet.swim();    // ❌ Compile Error (Only on Fish)

2. Intersection Types (&)

An intersection type combines multiple types into one type that has all the features of each. It is created using the ampersand (&) symbol.

interface Serializable {
  serialize(): string;
}
interface Loggable {
  log(): void;
}
 
type OutputModel = Serializable & Loggable;
 
const model: OutputModel = {
  serialize() { return "data"; },
  log() { console.log("Logged"); }
}; // ✅ Must implement both functions!

Intersection behavior on Primitives:

If you intersect two incompatible primitive types, you get never, because a value cannot be both a string and a number simultaneously:

type Impossible = string & number; // Type resolves to 'never'

3. Discriminated Unions

A common architectural pattern in TypeScript is the Discriminated Union (also called Tagged Unions). It is used to create clear, type-safe conditional logic by adding a common literal property (the "discriminant") to each member of the union.

interface SuccessResponse {
  status: "success"; // Discriminant
  data: string[];
}
 
interface ErrorResponse {
  status: "error"; // Discriminant
  message: string;
}
 
type ApiResponse = SuccessResponse | ErrorResponse;
 
function handleResponse(response: ApiResponse) {
  if (response.status === "success") {
    // TypeScript knows it is SuccessResponse here
    console.log(response.data);
  } else {
    // TypeScript knows it is ErrorResponse here
    console.log(response.message);
  }
}

Key Contrast Summary

Behavior FeatureUnion (|)Intersection (&)
Logic Meaninglogical OR (either type A OR B)logical AND (both type A AND B)
PrimitivesCreates a choice (string | number)Creates never (string & number)
Object PropertiesOnly common properties are accessibleAll properties of both types are accessible
Common Use CaseRepresenting alternative statesExtending/combining object shapes

Key Takeaways

  • Union Types: Created using | to allow a value to be one of several types, requiring narrowing to access non-common properties.
  • Intersection Types: Created using & to combine multiple types into a single type containing all members.
  • Primitive Intersection: Intersecting incompatible primitive types like string & number results in the never type.
  • Discriminated Unions: Leverage a literal discriminant property to perform clean, type-safe conditional logic.

Finished practicing this challenge?

Mark it as completed to track your progress, or bookmark it to review later.

Loading...

Share this Resource

Help other developers level up by sharing this study guide.

⚡ Weekly newsletter

Crack Your Next Frontend Interview.

Join senior engineers who receive practical, deep-dive frontend challenges, detailed concepts, and blueprints directly in their inbox.

  • Senior level React, JS, and CSS interview blueprints
  • System Design & performance optimization deep-dives
  • 100% free, zero spam, unsubscribe with one click

Join the Study Track

We value your privacy. Unsubscribe at any time.

More Technical Questions

Expand your mastery. Deep dive into other frontend interview challenges in this category.