Skip to content
Languages

Advanced TypeScript Patterns for Type Safety

November 15, 2024
10 min
Teknopulse
Advanced TypeScript Patterns for Type Safety

Advanced TypeScript Patterns for Type Safety

TypeScript goes beyond basic type checking. These patterns help you build more robust, maintainable code.

Discriminated Unions

Combine discriminators with union types:

type Result<T> = 
  | { status: 'success'; data: T }
  | { status: 'error'; error: string };

function handle<T>(result: Result<T>) {
  if (result.status === 'success') {
    console.log(result.data); // T is inferred
  } else {
    console.log(result.error); // string
  }
}

Generic Constraints

Limit generic types for safer code:

interface HasId { id: number }

function getById<T extends HasId>(items: T[], id: number) {
  return items.find(item => item.id === id);
}

Conditional Types

Type definitions based on conditions:

type Flatten<T> = T extends Array<infer U> ? U : T;

type Str = Flatten<string[]>; // string
type Num = Flatten<number>; // number

Utility Types

Built-in types for common patterns:

Exhaustiveness Checking

  • `Partial<T>` - Make all properties optional
  • `Required<T>` - Make all properties required
  • `Readonly<T>` - Make all properties readonly
  • `Pick<T, K>` - Select specific properties
  • `Omit<T, K>` - Exclude specific properties
  • `Record<K, T>` - Object with specific keys

Ensure all cases are handled:

type Status = 'pending' | 'success' | 'error';

function describe(status: Status): string {
  switch(status) {
    case 'pending': return 'Waiting...';
    case 'success': return 'Done!';
    case 'error': return 'Failed!';
    default: 
      const _exhaustive: never = status;
      return _exhaustive;
  }
}

These patterns transform TypeScript from a type checker into a powerful development tool.

Key Takeaways

Frequently Asked Questions

What are discriminated unions in TypeScript?

  • **Discriminated Unions**: Use a common property to create type-safe conditional logic for different variants.
  • **Generic Constraints**: Enforce structure on generic types using `extends` to ensure they meet specific requirements.
  • **Conditional Types**: Create dynamic type relationships that adapt based on the types provided.
  • **Utility Types**: Leverage built-in helpers like `Pick`, `Omit`, and `Partial` to transform existing types efficiently.
  • **Exhaustiveness Checking**: Use the `never` type to ensure all cases in a union are handled, preventing runtime errors.

Discriminated unions are a pattern where a common property (discriminator) is used to narrow down type in conditional logic, enabling type-safe handling of different variants.

When should I use generic constraints?

Use generic constraints when you need to limit what types can be passed to a generic function, ensuring the type has required properties or methods.

What are conditional types useful for?

Conditional types allow you to define type relationships based on conditions, enabling powerful type transformations and type-level programming.

How do utility types help in TypeScript?

Utility types like Partial, Required, Readonly, Pick, and Omit provide common type transformations that help you work with existing types more flexibly.

What is exhaustiveness checking?

Exhaustiveness checking ensures all possible cases are handled in switch statements or conditional logic, preventing runtime errors from unhandled cases.

TypeScriptProgrammingType Safety
← Back to All Articles

benihkode.web.id

Kebun digital untuk menanam ide, merawat eksperimen, dan memanen produk melalui kode.

Connect with Farmer

Subscribe to growing season updates

© 2025 benihkode.web.id. Built with love in the digital garden