All Articles
TypeScriptMay 8, 2026

TypeScript Patterns You'll

Actually Use

Skip the theory. These five patterns have saved our codebase from 90% of runtime errors.

RG

Ravi Gupta

Founder · ERVFlow

TypeScript Patterns You'll Actually Use

The Problem

Runtime errors don't come from nowhere — they come from types that are too loose. `string | undefined` everywhere, union-busting `as` casts, and `any` escape hatches that silently spread through a codebase.

The Solution

Five TypeScript patterns eliminate entire categories of runtime errors: discriminated unions model state correctly, branded types prevent ID confusion, Zod validates at boundaries, const assertions lock down literals, and satisfies checks type without widening.

Discriminated Unions

The most powerful TypeScript pattern for modelling state. Instead of optional fields that may or may not exist, each variant of your union carries exactly the data it needs.

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

Branded Types

Prevent passing a `UserId` where a `PostId` is expected, even though both are strings. Brands make the type system enforce your domain semantics.

Adopting These Patterns

1

Replace optional fields with discriminated unions

Instead of `{ status: string; data?: T; error?: string }`, use a union type per state. TypeScript now knows exactly what's available in each branch.

2

Brand your ID types

Create `type UserId = string & { readonly __brand: 'UserId' }`. Passing a `PostId` where a `UserId` is expected is now a compile-time error, not a runtime mystery.

3

Add Zod at every boundary

Parse external data (API responses, URL params, form inputs) with Zod schemas at the point of entry. Trust nothing from outside your type system.

4

Enable strict mode in tsconfig

Add `"strict": true` to tsconfig.json. Fix every error it surfaces — each one is a latent bug. Don't silence with `as` or `!`.

Key Takeaways

  • Discriminated unions eliminate impossible state by making invalid combinations unrepresentable
  • Branded types enforce domain semantics the compiler can't otherwise see
  • Zod bridges the gap between runtime data and TypeScript's static type system
  • Strict mode is not optional for production codebases — it's the minimum viable safety net

Frequently Asked Questions

Yes — every error strict mode surfaces is a real bug. Migrate incrementally with `// @ts-strict-ignore` on files you haven't touched yet.

ERVFlow generates type-safe code by default

Book a Demo

Book a Demo
TypeScriptPatternsDX
ERVFlow Newsletter

Stay ahead of the curve

Deep-dives on Next.js, AI, TypeScript, and DevOps — straight to your inbox.

© 2026ERVFlow· Made with using Next.js & Tailwind CSS

All rights reserved.