Utility Types
ts-utility-types
Code Snippets
TypeScript Generic Utility Types Tour
TypeScript ships with a rich set of utility types (`Partial`, `Pick`, `Awaited`) and the language is expressive enough that you can build the rest yourself. This snippet tours the three most useful custom utilities (`DeepPartial`, `ValueOf`, and an `Awaited` recap), each with a runtime sentinel that proves the type lines up with the value. Use it as a one-page cheat sheet before reaching for individual deep dives in the rest of the catalog.
DeepPartial Utility Type
`Partial<T>` only flips the top-level keys to optional, which is rarely enough for nested config or patch-style update payloads. `DeepPartial<T>` walks the type tree and makes every key at every depth optional. This snippet builds the basic recursive form, refines it for arrays and tuples so they are not flattened to objects, and pairs it with a deep-merge helper that consumes the type cleanly.
ValueOf Utility Type
`keyof` gives you the union of property names; `ValueOf<T>` gives you the union of property values. Combined with `as const` it derives a string-literal union from a single source-of-truth object, so the runtime constant and the static type can never drift. This snippet covers the one-line definition, an enum-replacement pattern, and a discriminator helper that drives type-safe `switch` blocks.
DeepReadonly Utility Type
`Readonly<T>` only freezes the top level, which is rarely enough for state objects passed across module boundaries. `DeepReadonly<T>` walks the type tree and marks every property `readonly` at every depth. This snippet builds the recursive form, refines it for arrays so they become `ReadonlyArray<T>`, and pairs it with `Object.freeze` so the runtime matches the type-level guarantee.
NonNullableKeys Utility Type
Filtering an object type to only the keys whose values are not nullable comes up everywhere: required-fields lists, mandatory column sets, GraphQL non-null fields. This snippet builds a `NonNullableKeys<T>` that returns just those keys, then layers in a `RequiredFields<T>` that produces a sub-object type, and a runtime helper that strips nullable fields from a value at runtime.
RequireAtLeastOne Utility Type
API endpoints often want 'pass at least one of these search params, but not necessarily all of them' (`{ id }`, `{ email }`, `{ id, email }`, but never `{}`). TypeScript's stock utilities cannot express that constraint, but a small `RequireAtLeastOne<T>` does. This snippet builds the type, layers in a `RequireExactlyOne` variant for either-or constraints, and shows a runtime guard that pairs with both.
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.
UnionToIntersection Utility Type
Going from a union (`A | B | C`) to an intersection (`A & B & C`) is what you need when you want to merge handler shapes, deduce the most-specific type, or express a 'must satisfy all branches' constraint. TypeScript has no built-in for this, but a single conditional with `infer` does the job. This snippet builds the type, walks through how distributive conditionals make it work, and ties it to a concrete LastInUnion / merged-handlers example.
Infer a Type from a Zod Schema
Maintaining a Zod runtime schema and a TypeScript interface that match by hand is a maintenance trap: every field change has to be edited twice. `z.infer<typeof Schema>` derives the static type from the schema, so the schema is the single source of truth. This snippet covers the basic infer pattern, the input/output split for transforms, and a typed parsing wrapper that turns runtime errors into a clean `Result` shape.
Fixed-Length Tuple via Generics
Constraining an argument to 'an array of exactly 4 numbers' is a common need (RGBA, 4x4 matrices, fixed-length feature vectors). TypeScript can express it with a recursive `TupleOf<T, N>` that builds up `[T, T, T, ...]` of the requested length. This snippet covers the recursive construction, a runtime helper that produces a value matching the type, and a length-comparison variant useful for richer constraints ("at least N", "between N and M").
