CodeBlanks Logo Icon CodeBlanks

Pattern matching

Learn branching with discriminated unions.

Pattern matching

Discriminated unions are processed with a switch statement; each case narrows to a member based on the discriminant value. This approach is called pattern matching. When all members are covered, TypeScript warns if a case is missing.

type Shape =
  | { kind: "circle"; radius: number }
  | { kind: "square"; size: number };

function area(s: Shape): number {
  switch (s.kind) {
    case "circle":
      return Math.PI * s.radius ** 2;
    case "square":
      return s.size ** 2;
  }
}

Exhaustiveness check

In a switch statement, if all members are covered by cases, TypeScript warns when a case is missing. Writing all cases instead of adding a default branch is safer; when a new member is added, the compiler shows where a case is missing.

type Shape =
  | { kind: "circle"; radius: number }
  | { kind: "square"; size: number };

function area(s: Shape): number {
  switch (s.kind) {
    case "circle": return Math.PI * s.radius ** 2;
    case "square": return s.size ** 2;
  }
}

Practice Shape area with switch

Define the Shape discriminated union type: "circle" (radius: number), "square" (size: number), "rectangle" (width: number, height: number) members, with a kind discriminant field. Write an area(s: Shape): number function using switch (s.kind). For circle return Math.PI * s.radius ** 2, for square return s.size ** 2, for rectangle return s.width * s.height. Print the result via console.log(area({ kind: "rectangle", width: 4, height: 5 })).

Starter code

index.ts
// Shape discriminated union türünü tanımla (kind discriminant, circle, square, rectangle üyeleri)

// area fonksiyonunu discriminant kontrolüyle switch ile yaz

// rectangle şeklinin alan sonucunu yazdır

Sample solution

index.ts
type Shape =
  | { kind: "circle"; radius: number }
  | { kind: "square"; size: number }
  | { kind: "rectangle"; width: number; height: number };

function area(s: Shape): number {
  switch (s.kind) {
    case "circle":
      return Math.PI * s.radius ** 2;
    case "square":
      return s.size ** 2;
    case "rectangle":
      return s.width * s.height;
  }
}

console.log(area({ kind: "rectangle", width: 4, height: 5 }));

Expected output

20

Questions and answers

Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.

1 Which construct is most suitable for processing a discriminated union?

  • try/catch
  • for loop
  • while loop
  • switch statement Correct answer

Explanation: A switch statement narrows to each member based on the discriminant value; each case corresponds to a member and provides pattern matching.

2 switch case narrowing

Question
type Shape =
  | { kind: "circle"; radius: number }
  | { kind: "square"; size: number };

function area(s: Shape): number {
  switch (s.kind) {
    case ____:
      return Math.PI * s.radius ** 2;
    case "square":
      return s.size ** 2;
  }
}
Answer
type Shape =
  | { kind: "circle"; radius: number }
  | { kind: "square"; size: number };

function area(s: Shape): number {
  switch (s.kind) {
    case "circle":
      return Math.PI * s.radius ** 2;
    case "square":
      return s.size ** 2;
  }
}

Explanation: The switch case "circle" narrows the Shape union to the circle member; inside the case body s.radius is safe to use.

3 Pattern matching parts

Term Meaning
switch ifadesi branch by discriminant
case "circle" narrows to circle member
Exhaustiveness check warns about missing case
default branch used when not all members covered

All lessons in Advanced