Built-in Utility Types: Partial, Pick, Omit, Record & friends
TypeScript ships ready-made type helpers that reshape an existing type for you — so you never rewrite a shape just to tweak it.
What you will learn
- Use Partial, Required, Readonly to flip optionality and mutability
- Reshape types with Pick, Omit and Record
- Pull types out of functions with ReturnType, Parameters and Awaited
Why reshape a type you already have?
Imagine you have a User interface. You constantly need slightly different versions of it: a version where every field is optional (for an update form), a version with only a couple of fields (for a list), or a version with one field removed (to hide a password). Rewriting the whole shape each time is tedious and drifts out of sync.
Utility types are built-in generic helpers that take a type in and hand a reshaped type back. You already know generics — these are just generics the TypeScript team wrote for you. They are the single most-used everyday tool in real codebases, so let us meet the important ones.
Partial<T> — make every property optional
A classic case: an "update" function that changes only *some* fields of a user. Partial<User> takes User and returns a copy where every property is optional.
interface User {
id: number;
name: string;
email: string;
}
function updateUser(id: number, changes: Partial<User>): void {
console.log('Updating user ' + id + ' with', changes);
}
updateUser(1, { name: 'Asha' }); // ok — only one field
updateUser(1, { email: 'a@x.com', name: 'A' }); // ok — two fieldsNote: Output:
Updating user 1 with { name: 'Asha' }
Updating user 1 with { email: 'a@x.com', name: 'A' }
Partial<User> is the same as { id?: number; name?: string; email?: string } — every field optional. So the caller may pass just the fields they want to change.
Required<T> and Readonly<T> — the other two flippers
Required<T> does the opposite of Partial: it makes every property mandatory. Readonly<T> makes every property read-only (set once, never reassigned).
interface Settings {
theme?: string; // optional in the original
fontSize?: number;
}
// Required: now BOTH are mandatory
const full: Required<Settings> = { theme: 'dark', fontSize: 14 };
// Readonly: the object is frozen at the type level
const locked: Readonly<Settings> = { theme: 'light' };
locked.theme = 'dark'; // error — read-onlyNote: Output:
Error: Cannot assign to 'theme' because it is a read-only property.
Required<Settings> forces every field to be present, so leaving out fontSize would error. Readonly<Settings> keeps the fields but blocks any later reassignment.
Pick<T, Keys> and Omit<T, Keys> — choose or drop fields
Often you want a smaller slice of a big type. Pick keeps only the named fields; Omit keeps everything *except* the named fields. The field names are written as a literal union in quotes.
interface User {
id: number;
name: string;
email: string;
password: string;
}
// Pick: a tiny "preview" with just two fields
type UserPreview = Pick<User, 'id' | 'name'>;
const p: UserPreview = { id: 1, name: 'Asha' };
// Omit: a "safe" user with password removed
type SafeUser = Omit<User, 'password'>;
const s: SafeUser = { id: 1, name: 'Asha', email: 'a@x.com' };
console.log(p.name, s.email);Note: Output:
Asha a@x.com
Pick<User, 'id' | 'name'> produces { id: number; name: string }. Omit<User, 'password'> produces the same shape as User but with password stripped out — perfect for data you send to the browser.
Record<Keys, Value> — build a lookup object type
Record<Keys, Value> describes an object whose keys come from a set and whose values all share one type. Great for dictionaries and lookup tables.
type Role = 'admin' | 'editor' | 'viewer';
// An object that maps every Role to a number (its permission level)
const levels: Record<Role, number> = {
admin: 3,
editor: 2,
viewer: 1
};
console.log(levels.editor);Note: Output:
2
Record<Role, number> means "an object with a key for each Role, each holding a number". If you forgot viewer, TypeScript would complain that a key is missing — so your lookup table can never be incomplete.
Pulling types out of functions: ReturnType, Parameters, Awaited
Some utilities read a type *out of* a function or promise, so you never hand-copy it:
ReturnType<typeof fn>— the type a function returns.Parameters<typeof fn>— a tuple of a function’s parameter types.NonNullable<T>—Twithnullandundefinedremoved.Awaited<T>— the value inside aPromise(whatawaitwould give you).
function makeUser(name: string, age: number) {
return { name, age, active: true };
}
// Grab the return shape automatically — no hand-typing
type NewUser = ReturnType<typeof makeUser>;
// NewUser is { name: string; age: number; active: boolean }
const u: NewUser = { name: 'Asha', age: 28, active: true };
console.log(u.active);
// Awaited unwraps a Promise's value type
type Data = Awaited<Promise<number>>; // Data is numberNote: Output:
true
ReturnType<typeof makeUser> extracted { name: string; age: number; active: boolean } straight from the function — so if makeUser ever changes, NewUser updates by itself. Awaited<Promise<number>> resolves to number.
The utility-type cheat sheet
| Utility | What it gives you |
|---|---|
Partial<T> | All properties optional |
Required<T> | All properties mandatory |
Readonly<T> | All properties read-only |
Pick<T, K> | Only the chosen properties |
Omit<T, K> | Everything except the chosen properties |
Record<K, V> | Object with keys K, all values V |
ReturnType<F> | A function’s return type |
Parameters<F> | A function’s parameter types as a tuple |
NonNullable<T> | T without null or undefined |
Awaited<T> | The value inside a Promise |
Tip: Reach for a utility type before you copy-paste a shape. Partial for update functions, Omit to hide sensitive fields, Pick for previews, and Record for lookup tables are the four you will use almost daily.
Watch out: Utility types only *reshape* types — they create no runtime code. Omit<User, 'password'> does not delete the password from a real object at runtime; it only changes what TypeScript will *accept*. To actually strip a field from data you still write normal JavaScript.
Q. You want an update function that accepts any subset of a User’s fields. Which utility type fits?
✍️ Practice
- Define a
Bookinterface, then createPick<Book, 'title' | 'author'>andOmit<Book, 'isbn'>types with matching objects. - Write a
Record<'mon' | 'tue' | 'wed', number>that maps three days to a step count.
🏠 Homework
- Take a
Productinterface (id, name, price, secretCost). Create aPublicProductwithOmit(no secretCost) and anUpdateProductwithPartial. Write a one-line note on when you would use each.