Last 30 Days
No notifications
Utility types are TypeScript's standard library of type-level helpers. Instead of copy-pasting modified versions of an interface, you compose them: Partial, Pick, ReturnType. Master the dozen most common ones and you'll cut your type code in half.
Imagine an API. You have a full User:
interface User {
id: number;
name: string;
email: string;
createdAt: Date;
}You want a "partial update" payload (PATCH /user). You could write a second interface — or use Partial:
type UserPatch = Partial<User>; // every field optionalThat's the spirit. Below are the ones you'll use weekly.
Partial — make every field optionaltype UserPatch = Partial<User>;
// { id?: number; name?: string; email?: string; createdAt?: Date }Required — make every field requiredUseful after Partial to "lock in" a defaults-merged object:
type Settings = { theme?: string; fontSize?: number };
function withDefaults(s: Settings): Required<Settings> { /* … */ }Readonly — make every field readonlytype FrozenUser = Readonly<User>;
const f: FrozenUser = { /* … */ };
// f.name = "x"; // ❌Pick — keep only certain keystype UserCard = Pick<User, "id" | "name">;
// { id: number; name: string }Omit — drop certain keystype UserPublic = Omit<User, "email">;
// { id: number; name: string; createdAt: Date }Pick and Omit together are the workhorses of any DTO layer.
Record — build an object maptype StatusCount = Record<"loading" "success"
"error", number>;
// { loading: number; success: number; error: number }type Dict = Record<string, number>; // open-ended
Exclude — remove memberstype T = "a" "b"
"c";
type Without = Exclude<T, "b">; // "a" "c"Extract — keep matching members
type Only = Extract<T, "a"
"z">; // "a"NonNullable — drop null & undefined
type Maybe = string
null
undefined;
type S = NonNullable<Maybe>; // stringParameters — tuple of arg typesfunction fetchUser(id: number, opts: { cache?: boolean }) { return null; }
type Args = Parameters<typeof fetchUser>;
// [number, { cache?: boolean }]ReturnType — return typetype R = ReturnType<typeof fetchUser>; // null (whatever it returns)function loadUser() { return { id: 1, name: "Ada" }; }
type User = ReturnType<typeof loadUser>; // { id: number; name: string }
This is the "infer the type from the implementation" trick — perfect when types live in code, not interfaces.
ConstructorParameters & InstanceTypeclass Box<T> { constructor(public value: T) {} }
type CParams = ConstructorParameters<typeof Box<string>>; // [string]
type Inst = InstanceType<typeof Box<string>>; // Box<string>Awaited — unwrap Promises (recursively)type A = Awaited<Promise<string>>; // string
type B = Awaited<Promise<Promise<number>>>; // numberPair with ReturnType for "what does this async function actually resolve to":
async function getUser() { return { id: 1 }; }
type User = Awaited<ReturnType<typeof getUser>>; // { id: number }type U = Uppercase<"hello">; // "HELLO"
type L = Lowercase<"WORLD">; // "world"
type C = Capitalize<"foo bar">; // "Foo bar"
type UC = Uncapitalize<"Foo">; // "foo"Combine with template literal types for handler-name generation, route building, etc.
interface User {
id: number;
name: string;
email: string;
password: string;
}// Public profile = User without password, every field readonly
type PublicProfile = Readonly<Omit<User, "password">>;
// Form = every field optional except id
type UserForm = Partial<User> & Pick<User, "id">;
Most utility types are simple mapped types under the hood:
type MyPartial<T> = { [K in keyof T]?: T[K] };
type MyReadonly<T> = { readonly [K in keyof T]: T[K] };
type MyPick<T, K extends keyof T> = { [P in K]: T[P] };Once these click, mapped/conditional types in Phase 4 will feel obvious.
| Want | Use |
| Make all fields optional | Partial |
| Make all fields required | Required |
| Make all fields immutable | Readonly |
| Keep only some keys | Pick |
| Drop some keys | Omit |
| Build a map | Record |
| Remove union members | Exclude |
| Keep union members | Extract |
| Strip null/undefined | NonNullable |
| Get function's args | Parameters |
| Get function's return | ReturnType |
| Unwrap promise | Awaited |