TypeScript Tricks I Use Daily
Ankit Singh
Engineering

TypeScript Tricks I Use Daily

STACK TS 5.xTOOLS Type-safe codebaseDATE May 2025READ 7 min
TypeScriptEngineeringDX

Most TypeScript tutorials stop at interfaces and generics. Here are the patterns I reach for daily that make codebases dramatically safer and more expressive.

Discriminated Unions Are Underused

If you're using a boolean flag to represent state, you're probably holding it wrong. Discriminated unions encode state transitions into the type system itself. The compiler tells you when you've forgotten a case.

type AsyncState =
  | { status: 'idle' }
  | { status: 'loading' }
  | { status: 'success'; data: T }
  | { status: 'error'; error: Error };

Template Literal Types

These sound academic until you use them for event names, CSS class generation, or API route typing. You can encode entire naming conventions in the type system.

Branded Types for Semantic Safety

A UserId and an OrderId are both strings. TypeScript doesn't care. Branded types make them incompatible, which catches entire categories of bugs at compile time rather than runtime.

The satisfies Operator

Added in TS 4.9 and still underused. It validates that a value matches a type without widening the inferred type. Perfect for config objects where you want both safety and precise inference.

Conditional Types in Practice

Deep conditional types look scary. In practice, 90% of use cases are: "if this prop is passed, require this other prop." The infer keyword unlocks extracting types from other types — essential for wrapping third-party library types.

TypeScript Performance in Large Codebases

When type checking takes more than 10 seconds, the team stops using it properly. Use tsc --generateTrace to profile slow types. The usual culprits: deeply recursive types, excessive union members, and circular imports.