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:
| Utility | Meaning |
|---|---|
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.