How do Partial, Required and Readonly transform object types?
Take a moment.
Say your answer out loud or write it down first — retrieval is what makes it stick. Reveal when you're ready.
Short answer
They're mapped types: Partial<T> makes every property optional (draft/update shapes), Required<T> makes every property non-optional, Readonly<T> marks every property readonly. Each iterates over keyof T and applies a modifier.
Detailed explanation
Mapped types iterate keys and rebuild properties with modifiers: { [K in keyof T]?: T[K] } is essentially Partial. Partial shines for update payloads — patchUser(id, changes: Partial<User>) accepts any subset without duplicating the interface. Required is its inverse, stripping optionality (useful after validation guarantees completeness). Readonly protects inputs from mutation contracts. Modifiers combine: Readonly<Partial<T>> for frozen drafts. You can remove modifiers with -?: { [K in keyof T]-?: T[K] } — that's literally Required's implementation. Custom mapped types follow the same recipe, e.g., making only certain methods nullable or stringifying all values ({ [K in keyof T]: string }). Understanding that these utilities are *just syntax sugar over mapped types* is what lets you write your own domain-specific variants.
Example
interface User { id: number; name: string; email?: string }
type UserPatch = Partial<User>; // all optional
function updateUser(id: number, patch: UserPatch) {}
updateUser(1, { name: 'New' }); // ✅ subset ok
type StrictUser = Required<User>; // email now required
// Under the hood:
type MyPartial<T> = { [K in keyof T]?: T[K] };Interview tip
Define 'mapped type' first, then present each utility as one application of it. Writing MyPartial on the spot proves deep understanding instantly.
Common mistakes
- Not knowing these are built from mapped-type syntax.
- Using Partial everywhere instead of modeling precise update types.