TypeScript

TypeScript Utility Types Cheat Sheet

Partial, Pick, Omit, Record, and the other built-in utility types explained with practical, real-world examples instead of abstract definitions.

Ava ChenJuly 14, 20263 min read
Share:

TypeScript ships a set of built-in type transformations that cover most of the "I need a slightly different version of this type" situations you'll hit. Here's the practical reference.

Partial<T> — make every field optional

ts
interface User {
  id: string;
  name: string;
  email: string;
}
 
function updateUser(id: string, changes: Partial<User>) {
  // changes might only include { name: "New Name" }
}

The canonical use case: update functions that accept a subset of fields to change.

Required<T> — the opposite, make every field mandatory

ts
interface Config {
  timeout?: number;
  retries?: number;
}
 
function runWithDefaults(config: Required<Config>) {
  // both fields guaranteed present at this point
}

Useful after you've merged user input with defaults and want the type system to confirm nothing is missing.

Pick<T, K> — select a subset of fields

ts
type UserPreview = Pick<User, "id" | "name">;
// { id: string; name: string }

Omit<T, K> — the inverse, exclude fields

ts
type UserWithoutEmail = Omit<User, "email">;
// { id: string; name: string }

Pick and Omit solve the same problem from opposite directions — use whichever needs fewer keys listed.

Record<K, V> — a typed dictionary

ts
type StatusColors = Record<"pending" | "active" | "done", string>;
// { pending: string; active: string; done: string }
 
const colors: StatusColors = {
  pending: "#eab308",
  active: "#22c55e",
  done: "#64748b",
};

Record is what you reach for instead of { [key: string]: V } when you know the exact set of valid keys — TypeScript will then error if you forget one or typo a key.

Readonly<T> — prevent reassignment

ts
const config: Readonly<Config> = { timeout: 5000, retries: 3 };
config.timeout = 1000; // Error: Cannot assign to 'timeout' because it is a read-only property

Only a compile-time guarantee — it doesn't freeze the object at runtime like Object.freeze() does.

ReturnType<T> — extract a function's return type

ts
function createUser() {
  return { id: crypto.randomUUID(), createdAt: new Date() };
}
 
type NewUser = ReturnType<typeof createUser>;

Genuinely useful when the return type is inferred and complex — you get the type without duplicating the shape by hand, and it stays in sync automatically if the function changes.

Combining them

These compose naturally:

ts
type UserUpdate = Partial<Omit<User, "id">>;
// every field optional except id is excluded entirely

That's the real payoff — instead of hand-writing a new interface for every variation of a shape you need, you derive it from one source of truth.

Advertisement
Ava Chen
Ava Chen

Senior Software Engineer

Ava writes about frontend architecture, React, and TypeScript. Previously built developer tools at scale-up startups.

Related Articles