Capítulo 30 de 36

Chapter 30: Utility Types

Core Idea

TypeScript ships a set of globally-available generic helper types — mostly thin wrappers around mapped types, conditional types, and infer — covering the transformations needed constantly enough (optional-ify, pick/omit fields, extract a function's return type, strip null/undefined) that hand-writing them every time would be wasteful. This chapter is the single most-consulted reference in this skill — check the table below before writing a custom mapped/conditional type from scratch.

Key Concepts — grouped by purpose

Object-shape transforms (mapped types under the hood)

  • Partial<T>: every property becomes optional — models "a subset of T's fields," the standard type for a patch/update payload.
  • Required<T>: the inverse — every property becomes required, stripping ?.
  • Readonly<T>: every property becomes readonly — useful for typing the result of Object.freeze-like operations, so an accidental reassignment is a compile error.
  • Record<K, T>: builds an object type with every key from K (typically a union of string/number/symbol literals) mapped to value type T — the standard way to type a lookup/dictionary with a known, closed key set. Unlike Partial/Required/Readonly, it's not homomorphic — it manufactures brand-new properties from K rather than transforming an existing type's own properties, so there's nothing to copy modifiers from.
  • Pick<T, K>: keeps only the properties named in K (a literal or union of literal keys) from T.
  • Omit<T, K>: the inverse of Pick — keeps every property of T except the ones named in K.

Union filtering (conditional types + distribution under the hood)

  • Exclude<UnionType, ExcludedMembers>: removes every union member assignable to ExcludedMembers.
  • Extract<Type, Union>: the inverse — keeps only union members assignable to Union.
  • NonNullable<T>: shorthand for Exclude<T, null | undefined> — strips both nullish types from a union in one step.

Function/class introspection (built on infer)

  • Parameters<T>: extracts a function type's parameter list as a tuple type. For an overloaded function, resolves against the last signature only (same limitation as infer generally — TS can't do overload resolution from a type alone).
  • ConstructorParameters<T>: like Parameters<T>, but for a constructor function type — produces never if T isn't a constructor type.
  • ReturnType<T>: extracts a function type's return type. Same last-overload-only caveat as Parameters.
  • InstanceType<T>: extracts the type an constructor function produces when new'd — the general-purpose version of "class → instance type," typically used as InstanceType<typeof SomeClass>.
  • ThisParameterType<T>: extracts the declared this parameter's type from a function type, or unknown if the function has none.
  • OmitThisParameter<T>: strips a declared this parameter from a function type, producing a callable type usable without needing to supply/bind this first (e.g. after .bind()). Generics are erased in the process, and only the last overload survives if the source was overloaded.

Inference control

  • NoInfer<T> (5.4+): wraps a type parameter usage to exclude that position from contributing to inference — e.g. a defaultColor?: NoInfer<C> parameter won't itself widen/narrow what C gets inferred as from the primary colors: C[] argument, so passing a default outside the inferred set of colors becomes a compile error instead of silently widening the color union to include it.
  • ThisType<T>: not a type transform at all — a marker interface (empty, declared in lib.d.ts) that TypeScript's object-literal contextual-typing machinery specifically recognizes: putting ThisType<D & M> on a methods property's type makes this inside those methods resolve to D & M. Requires noImplicitThis. This is the mechanism behind "options object with methods that need typed access to sibling data/methods" APIs (e.g. Vue 2-style component options).

String literal transforms

  • Uppercase<S> / Lowercase<S> / Capitalize<S> / Uncapitalize<S>: intrinsic (compiler-built-in) string literal type transforms — full treatment lives in the Template Literal Types chapter; they're globally available the same way the other utility types here are.

Awaited<T> (4.5+)

  • Models what await/Promise.prototype.then actually do: recursively unwraps nested Promises (Promise<Promise<number>> unwraps all the way to number, not just one level), and passes non-Promise members of a union through unchanged (Awaited<boolean | Promise<number>> is boolean | number).

Code Examples

interface Task { title: string; done: boolean }
function patch(task: Task, changes: Partial<Task>): Task {
  return { ...task, ...changes };
}
  • What it demonstrates: Partial<T> typing an "update payload" parameter that may supply any subset of a type's fields.
interface User { id: number; name: string; email: string; passwordHash: string }
type PublicUser = Omit<User, "passwordHash">;
  • What it demonstrates: Omit deriving a "safe to expose" shape from a full internal type by name-listing the field(s) to drop.
declare function getUser(id: number): { id: number; name: string };
type User = ReturnType<typeof getUser>; // { id: number; name: string }
  • What it demonstrates: ReturnType + typeof deriving a named type from an existing function's inferred return shape, instead of duplicating the shape by hand.

Reference Tables

UtilitySignatureWhat it does
Partial<T>Partial<T>all properties optional
Required<T>Required<T>all properties required
Readonly<T>Readonly<T>all properties readonly
Record<K, T>Record<K, T>build object type: keys K, values T
Pick<T, K>Pick<T, K>keep only keys K
Omit<T, K>Omit<T, K>drop keys K
Exclude<U, M>Exclude<U, M>remove union members assignable to M
Extract<T, U>Extract<T, U>keep union members assignable to U
NonNullable<T>NonNullable<T>drop null/undefined
Parameters<T>Parameters<T>function's params as a tuple
ConstructorParameters<T>ConstructorParameters<T>constructor's params as a tuple
ReturnType<T>ReturnType<T>function's return type
InstanceType<T>InstanceType<T>constructor's instance type
NoInfer<T>NoInfer<T>exclude a position from inference
ThisParameterType<T>ThisParameterType<T>a function's declared this type, or unknown
OmitThisParameter<T>OmitThisParameter<T>strip a declared this parameter
ThisType<T>marker onlysets contextual this inside an object literal's methods (needs noImplicitThis)
Awaited<T>Awaited<T>recursively unwrap nested Promises

Key Takeaways

  1. Reach for one of these before hand-writing a mapped/conditional type — Partial/Required/Readonly/Pick/Omit/Record cover the overwhelming majority of "shape transform" needs.
  2. Parameters/ReturnType/ConstructorParameters/InstanceType are the standard way to derive a type from an existing function/class instead of duplicating its shape by hand — pair with typeof when starting from a value rather than a type name.
  3. Record is not homomorphic (unlike Pick/Partial/Readonly) — it can't copy modifiers from a source type because it doesn't have one; it manufactures fresh properties from a key union.
  4. Parameters/ReturnType on an overloaded function only see the last signature — don't rely on them to model overload resolution.

Connects To

  • Mapped Types: the underlying mechanism for Partial/Required/Readonly/Pick/Record.
  • Conditional Types: the underlying mechanism for Exclude/Extract/NonNullable/ReturnType/Parameters/InstanceType.
  • Template Literal Types: full treatment of Uppercase/Lowercase/Capitalize/Uncapitalize.
  • Generics: NoInfer and the constructor-signature-based utilities build directly on generic inference mechanics.