Script Valley
TypeScript: Complete Course from Zero
Functions and Type NarrowingLesson 3.4

Type guards and custom type predicates in TypeScript

type predicate syntax, is keyword, user-defined type guards, discriminated unions, type assertion vs type guard

Type predicates

A type predicate is a return type of the form paramName is Type. When the function returns true, TypeScript narrows the argument to that type:

function isString(value: unknown): value is string {
  return typeof value === "string";
}

function process(input: unknown) {
  if (isString(input)) {
    console.log(input.toUpperCase()); // string
  }
}

Discriminated unions

Add a shared literal property to distinguish union members — TypeScript narrows on it automatically:

interface Circle  { kind: "circle";  radius: number; }
interface Square  { kind: "square";  side: number;   }
type Shape = Circle | Square;

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

The discriminant property (kind) should be a string literal type, not a general string. This pattern is the most reliable way to handle heterogeneous unions and composes well with the never exhaustive check pattern from Lesson 1.5.

Up next

Higher-order functions and function types in TypeScript

Sign in to track progress