Frontend Patterns

Pattern

Type Guard

Write functions that narrow types at runtime for safe type assertions.

Type Guard

Problem

TypeScript can’t infer specific types from conditional checks, forcing developers to use unsafe type assertions or ignore type errors. Union types remain too broad after validation, requiring casts that bypass type safety. Runtime checks exist but don’t help the type system, leaving code littered with type assertions and potential runtime crashes.

Solution

Write functions that narrow types based on runtime checks. This gives TypeScript information to provide accurate types in conditional branches.

Example

This demonstrates writing type guard functions that narrow types based on runtime checks, giving TypeScript accurate type information in conditional branches without unsafe type assertions.

// Type guard function with 'is' predicate
function isUser(obj: any): obj is User {
  // Runtime validation that informs TypeScript's type system
  return obj && typeof obj.name === 'string' && typeof obj.email === 'string';
}

if (isUser(data)) {
  // TypeScript knows data is User here - no type assertion needed
  console.log(data.email);  // Safe access to email property
}

Benefits

  • Eliminates unsafe type assertions by narrowing types correctly.
  • Provides runtime validation that informs the type system.
  • Makes code more maintainable with explicit type checking logic.
  • Enables safer handling of union types and unknown data.

Tradeoffs

  • Requires writing and maintaining type guard functions.
  • Can be verbose for complex type checks.
  • Runtime checks add small performance overhead.
  • Type guards can become stale if types change but guards don’t update.
Stay Updated

Get New Patterns
in Your Inbox

Join thousands of developers receiving weekly insights on frontend architecture patterns

No spam. Unsubscribe anytime.