121 — Utility Types, Blazing Fast (Object Shapers, Union Operators, Extractors)
Full companion narrative for Matt Pocock's TypeScript Utility Types Blazing Fast — the global no-import helpers in three families plus a composed ReturnType and Awaited challenge
Video: 121 · TypeScript’s Utility Types, Blazing Fast · watch · ~03:08 · Matt Pocock
Source: this is a written companion to the video. Part of the Favorite TypeScript Videos curated path, module 03 (advanced types) — the helper catalog for the whole path: the object shapers carve the price map from 120, the union operators shrink the constrained unions from 119,
NonNullableis the type-level twin of the?.narrowing in 118, andPartialmeets its strictest interaction in 114.
Matt speed-runs one file, ideas/utility-types/src/index.ts, straight through — each helper gets one typed line and its hover result, then he moves on. His opener sets the terms: “The utility types are a set of types that are available globally in all TypeScript projects. So you don’t need to add any dependencies to get this going.” Every utility type, he adds, is just available in the project without needing to import anything. Frame one freezes the object section (Omit<User, "id">), frame two the discriminated-union setup (RoleAttributes), frame three the async tail (Promise<string>).

object shapers: Partial, Required, Omit, Pick, Readonly
Partial<User> makes every property optional — the update-payload shape where any subset of fields is legal — while Required drives optional properties back to required where a downstream step must see the complete object. Omit<User, "id"> returns the object minus a property, passing a union removes several at once, and Pick is the reverse that keeps only the named properties. They compose: Partial<Pick<User, "id" | "name">> yields id and name both optional. Readonly<User> freezes assignment, and its missing inverse is a hand-written mapped type that strips readonly — the first hint that utility types are themselves composable type-level programs. Note the strictness interaction: every property Partial makes optional becomes absent-or-present-never-undefined under the exactOptionalPropertyTypes flag from 114.
type User = { id: string; name: string; age: number };
type UserUpdate = Partial<User>; // all props optional
const patch: UserUpdate = { name: "k" }; // ok: subset legal
type NoId = Omit<User, "id">; // { name: string; age: number }
type JustIdName = Partial<Pick<User, "id" | "name">>; // both optional
type Frozen = Readonly<User>; // id, name, age all read-only
type Mutable<T> = { -readonly [K in keyof T]: T[K] }; // hand-rolled inverse
union operators: Exclude and Extract on discriminated unions
On the RoleAttributes discriminated union — where only the admin member carries orgId — Exclude drops members and accepts a union to drop several, while Extract pulls out a single member by its discriminator so its extra properties become examinable. These are the operators that shrink or select within constrained unions like the <TItem extends Animal | Human> parameter from 119 before such unions reach a signature, and they operate on the object shape that 120 ends with — an as const price map is directly Pick-able where a numeric enum is not.
type RoleAttributes = { role: "admin"; orgId: string } | { role: "user" } | { role: "anonymous" };
type NonAdmin = Exclude<RoleAttributes, { role: "admin" }>; // user | anonymous
type AdminOnly = Extract<RoleAttributes, { role: "admin" }>; // { role: "admin"; orgId: string }

function and async extractors: ReturnType, Parameters, NonNullable, Awaited
For funk(a: number, b: string): number, ReturnType<typeof funk> tracks the return type through later edits and Parameters<typeof funk> yields the named tuple [a: number, b: string] — the fix when an external library never exported those types. NonNullable<string | null | undefined> strips the nil members, the type-level twin of the ?. guard at the use site in 118. Promise<string> represents the async value and Awaited unwraps it. The closing challenge composes all three families: Awaited<ReturnType<typeof asyncFunk>> extracts the resolved value out of an async function’s promise.
declare function funk(a: number, b: string): number;
type R = ReturnType<typeof funk>; // number, tracks edits
type P = Parameters<typeof funk>; // [a: number, b: string], tracks added params
type Clean = NonNullable<string | null | undefined>; // string
declare function asyncFunk(): Promise<number>;
type Resolved = Awaited<ReturnType<typeof asyncFunk>>; // number
const n: Resolved = 42; // ok: unwrapped, not Promise<number>

The helper catalog the path builds on: object shapers carve shapes like the price map from 120, union operators select within constraints like the one in 119, and the same object-shaping family reappears as the scraper’s Record<string, unknown> accumulator in 123. Watch the Partial interplay with 114’s exactOptionalPropertyTypes before shipping update payloads.
Prev: 120 — TypeScript Enums Explained · Next: 122 — Design Patterns Intro
Transcript notes: type and helper names verified against the editor frames; screenshots sample one frame per family, timestamps ~00:00 (objects) through ~02:00 (async) across the ~03:08 runtime.