Type Narrowing
ts-type-narrowing
Code Snippets
Branded (Nominal) Types
TypeScript is structurally typed, so `type UserId = string` and `type OrderId = string` are interchangeable to the compiler, which is exactly the bug class you want to prevent. Branded (nominal) types attach a phantom tag so the two stay distinct at compile time without any runtime cost. This snippet covers the basic brand pattern, a parser-style smart constructor that produces a brand from a raw value, and a multi-brand domain model that ties them together.
isDefined Type Guard
Filtering an array of `(T | undefined)[]` should leave you with `T[]`, but `Array.prototype.filter(Boolean)` leaves the type as `(T | undefined)[]` because the compiler does not understand the predicate. A user-defined type guard with the `value is T` return type fixes the inference. This snippet covers the basic `isDefined`, an `isNonNullable` variant that also drops `null`, and a generic `compact` that uses the guard to narrow at the array level.
Exhaustive assertNever Switch
Discriminated unions are TypeScript's superpower for state machines, redux reducers, and API response shapes, but a `switch` over them silently goes stale the moment a new variant appears. The `assertNever` helper flips silent staleness into a compile error: any unhandled branch means the type passed in is not actually `never`. This snippet covers the helper, a reducer that uses it for compile-time safety, and an interim `default` strategy for production safety while you iterate.
