Built-in Type Transformations You'll Use Daily
Utility Types
TypeScript ships a set of utility types — `Partial`, `Pick`, `Omit`, `Record`, `ReturnType`, and more. Learn them and reach for them.
What you'll learn
- Recognize the most common utilities
- Pick the right one for the job
- Know that they're just mapped + conditional types underneath
The standard library ships a stack of utility types — generic
helpers for the transformations you do all the time. They’re all
built from the primitives in the last chapter (mapped, conditional,
infer).
Partial<T> — All Optional
type User = { id: string; name: string; email: string };
type UserUpdate = Partial<User>;
// { id?: string; name?: string; email?: string }
function patch(id: string, changes: Partial<User>) { /* ... */ }
patch("u1", { name: "Ada" }); // ok — only some keys Every property becomes optional. Use it for update/patch shapes.
Required<T> — All Required
type Config = { host?: string; port?: number };
type FullConfig = Required<Config>;
// { host: string; port: number } The opposite of Partial.
Readonly<T> — All Readonly
type Frozen = Readonly<User>;
// { readonly id: string; readonly name: string; ... } For things you don’t want callers to mutate.
Pick<T, K> — Choose Keys
type UserSummary = Pick<User, "id" | "name">;
// { id: string; name: string } Keep only the listed keys.
Omit<T, K> — Exclude Keys
type PublicUser = Omit<User, "email">;
// { id: string; name: string } The opposite of Pick.
Record<K, V> — Object Map
type Lookup = Record<string, number>;
const counts: Lookup = { a: 1, b: 2 };
type RoleFlags = Record<"admin" | "user" | "guest", boolean>;
// { admin: boolean; user: boolean; guest: boolean } Build an object type with a known key set and uniform value type.
Exclude<T, U> and Extract<T, U>
Work on unions (using distributive conditionals from the last lesson):
type Color = "red" | "green" | "blue" | "alpha";
type Solid = Exclude<Color, "alpha">; // "red" | "green" | "blue"
type Primary = Extract<Color, "red" | "blue">; // "red" | "blue" NonNullable<T> — Drop null / undefined
type Maybe = string | null | undefined;
type Defined = NonNullable<Maybe>; // string Parameters<F> and ReturnType<F>
function greet(name: string, age: number): string {
return `${name}, ${age}`;
}
type Args = Parameters<typeof greet>; // [name: string, age: number]
type R = ReturnType<typeof greet>; // string Wrapping someone else’s function? These let you stay in sync with its signature.
Awaited<T> — Unwrap Promises
type T1 = Awaited<Promise<string>>; // string
type T2 = Awaited<Promise<Promise<number>>>; // number (recursive) Awaited resolves nested promises down to the final value. Handy
when typing the return of an async function chain.
The Big Table
| Utility | What it does |
|---|---|
Partial<T> | All properties optional |
Required<T> | All properties required |
Readonly<T> | All properties readonly |
Pick<T, K> | Subset of keys |
Omit<T, K> | All keys except K |
Record<K, V> | Object map with key set K, values V |
Exclude<T, U> | Union minus U |
Extract<T, U> | Union members assignable to U |
NonNullable<T> | Drop null / undefined |
Parameters<F> | Tuple of parameter types |
ReturnType<F> | Function’s return type |
Awaited<T> | Unwrap nested promises |
InstanceType<C> | Instance type from a class constructor |
ConstructorParameters<C> | Tuple of constructor params |
Compose Them
Utilities compose:
type EditableFields = Partial<Omit<User, "id">>;
// { name?: string; email?: string } Patch shape, minus the id (you don’t change a user’s id by patching).
Up Next
Branded types — making UserId and OrderId actually different
even though they’re both string.