Course outline · 0% complete

0/26 lessons0%

Course overview →

Partial, Pick, and Omit

lesson 7-1 · ~11 min · 21/26

Quiz

Warm-up from lesson 6-2: Box<T> was an interface with a type slot. Built-in utility types like Partial<T> are the same idea. What would you guess Partial<Settings> produces?

Types made from other types

TypeScript ships utility types, generic types that transform existing ones. They exist because real projects constantly need variations of one shape — the same user with fields optional for an update form, or with private fields removed for display — and hand-writing each variation means shapes that drift out of sync. The ones you will use weekly:

UtilityMeaning
Partial<T>every property of T becomes optional
Pick<T, K>keep only the listed properties
Omit<T, K>keep everything except the listed properties
Readonly<T>every property of T becomes readonly

The classic Partial use case is an update function. Callers change one setting, not all three:

interface Settings {
  theme: string;
  fontSize: number;
  autosave: boolean;
}

function applyChanges(base: Settings, changes: Partial<Settings>): Settings {
  return { ...base, ...changes };
}

The spread syntax from Advanced JavaScript merges the objects, and the types guarantee changes only ever contains valid Settings properties.

Readonly<T> applies lesson 3-2's readonly to every property at once, for values that must never be mutated after creation.

Code exercise · typescript

Run it. The changes object supplies only theme, the rest comes from base. Then try passing { theme: "dark", fontSizes: 16 } and watch the typo get caught.

Pick and Omit: sub-shapes without duplication

The server behind a web API should never send passwordHash to the browser. Instead of writing a second interface by hand and keeping it in sync forever, derive it:

interface User {
  id: number;
  name: string;
  email: string;
  passwordHash: string;
}

type PublicUser = Omit<User, "passwordHash">;
type UserPreview = Pick<User, "id" | "name">;

PublicUser has everything except the hash. UserPreview has only id and name, note the union of literal property names from Unit 4. When User gains a field, the derived types update themselves.

Code exercise · typescript

Your turn. Given interface Task { title: string; done: boolean }, write updateTask(task: Task, changes: Partial<Task>): Task using spread merge. Start from t = { title: "study", done: false }, produce finished by updating done to true, then print both lines shown in the expected output.