Pick & Omit
Select what you want, or remove what you don't — surgical type precision
Pick<T, K> lets you SELECT specific properties from a type. Omit<T, K> lets you EXCLUDE specific properties from a type. They're opposites that achieve the same goal — creating a smaller, focused type from a larger one.
Think of the Irani chai plate at Nimrah Cafe. When the chai arrives, it comes with a FULL plate of possible sides — Osmania biscuit, Chai biscuit, Lukhmi, Samosa, Dil Khush, Pastry. The FULL plate is your original type.
Pick is when you point and say "Bhai, mujhe SIRF Osmania biscuit aur samosa chahiye" — you PICK only those two. Omit is when you say "Bhai, sab dedo BAS lukhmi mat dena" — you OMIT just the one you don't want. Both get you a smaller selection, but your APPROACH is different.
Pick = "I want ONLY these." Omit = "I want everything EXCEPT these." Seedha samjho: Pick = select karke lo, Omit = nikal ke baaki sab lo!
These two utility types are among the most commonly used in TypeScript. Every time you create a type for an API response that shouldn't include a password, or a form that only needs a few fields, you're using the chai plate selection logic. You start with the full set and carve out exactly what the situation demands. No duplication, no maintenance headaches — just precise, derived types that stay in sync with the original automatically.
Pick<T, K> creates a new type by selecting only the properties whose keys are in K. The syntax is straightforward: you provide the original type and the keys you want to keep.
interface User {
id: string;
name: string;
email: string;
age: number;
password: string;
}
// Pick only these 3 properties
type PublicUser = Pick<
User,
"id" | "name" | "email"
>;
// { id: string; name: string; email: string }
You can pick a single property too: Pick<User, "name"> gives you { name: string }. The power comes from the fact that K must be a subset of keyof T — if you try Pick<User, "foo">, TypeScript throws an error because "foo" is not a key of User.
Under the hood, Pick is implemented using a mapped type:
type Pick<T, K extends keyof T> = {
[P in K]: T[P];
};
It iterates over the selected keys in K and copies their types from T. Simple and elegant!
Real-world use cases are everywhere: (1) API responses — type UserResponse = Pick<User, "id" | "name" | "email"> — never expose the password. (2) Form fields — type CreateUserForm = Pick<User, "name" | "email" | "password"> — only the fields a new user fills in; the id is generated server-side. (3) List items — type UserListItem = Pick<User, "id" | "name"> — minimal data for a list view, no need to load the full object. Pick keeps your types lean and purposeful.
Omit<T, K> creates a new type by REMOVING the properties whose keys are in K. It's the complement of Pick. Where Pick says "keep only these," Omit says "remove these and keep everything else."
interface User {
id: string;
name: string;
email: string;
age: number;
password: string;
}
// Remove just the password
type SafeUser = Omit<User, "password">;
// { id, name, email, age }
// Remove multiple properties
type BasicUser = Omit<
User,
"password" | "age"
>;
// { id, name, email }
Omit is implemented using Pick and Exclude together:
type Omit<T, K extends keyof T> =
Pick<T, Exclude<keyof T, K>>;
This means: (1) Get all keys of T using keyof T, (2) Remove the keys in K using Exclude, (3) Pick the remaining keys. Omit is literally Pick in disguise — it just calculates the keys to keep by excluding the ones you don't want!
Real-world use cases: (1) Removing sensitive fields — Omit<User, "password"> for public API responses. (2) Creating update types — type UserUpdate = Omit<User, "id"> — you can't change the id, so it's removed from the update payload. (3) Guest types — type GuestUser = Omit<User, "email" | "password"> — a guest user doesn't have email or password fields.
One interesting detail: in newer TypeScript (4.x+), Omit's K doesn't need to be a strict subset of keyof T. Omit<User, "nonexistent"> won't error — it just has no effect, returning the original type. This is useful when working with dynamic keys, but be explicit when you can!
Pick and Omit are straightforward, but they come with traps that can trip you up. Let's walk through the most common ones.
Trap 1: Pick vs Omit confusion. If you want 2 out of 10 properties, use Pick (shorter K). If you want 8 out of 10, use Omit (shorter K). Choose whichever has a SMALLER K! Using Omit to remove 8 keys when you could Pick 2 keys is verbose and error-prone.
Trap 2: Omit with non-existent keys. In TS 4.x+, Omit<User, "foo"> doesn't error — it silently does nothing. In older versions, behavior varied. Don't rely on this; be explicit with your keys.
Trap 3: Pick doesn't always preserve method signatures. If the original type has methods with this references, Pick may break the this binding. This is rare but nasty when it hits.
Trap 4: Omit doesn't remove NESTED properties.
// ERROR! Can't omit nested keys
type NoSecret = Omit<
{ user: { name: string; secret: string } },
"user.secret"
>;
You can only omit top-level keys. For deep omitting, you need a custom recursive utility type — the built-in Omit only works on the surface.
Trap 5: Repeated Pick/Omit chains.
// Works but hard to read
type Result = Pick<
Omit<User, "password">,
"id" | "name"
>;
// Prefer single operation
type Result2 = Pick<
User, "id" | "name"
>;
Nesting Pick inside Omit works, but it's harder to read and reason about. Combine the logic into a single operation when possible. The simpler your type expression, the easier it is for your team to understand and maintain.
Time for the rapid-fire cheatsheet. Pin this to your desk or write it on your chai plate — whatever works!
Pick Cheatsheet:
// Select only keys in K
type Result = Pick<T, K>;
// Example
type PublicUser = Pick<
User, "id" | "name"
>;
// Implementation
type Pick<T, K extends keyof T> = {
[P in K]: T[P];
};
Omit Cheatsheet:
// Remove keys in K
type Result = Omit<T, K>;
// Example
type SafeUser = Omit<User, "password">;
// Implementation
type Omit<T, K extends keyof T> =
Pick<T, Exclude<keyof T, K>>;
Common Patterns:
- Safe API response —
Omit<User, "password"> - Form type —
Pick<User, "name" | "email"> - Update type —
Omit<User, "id"> - List item —
Pick<User, "id" | "name">
Key Rules:
- Pick = "sirf yeh chahiye," Omit = "bas yeh nahi chahiye"
- Neither modifies nested properties — top-level only
- Pick requires K to be a subset of keyof T
- Choose whichever has the smaller K for cleaner code
- Avoid deeply chained Pick/Omit — simplify when possible
The golden rule: "Pick and Omit are the chai plate jugaad — select what you want, or remove what you don't. Biryani mein se khatta nikalna (Omit) ya sirf gosht lena (Pick) — your choice, bhai!"
Key Takeaways
- Pick
selects only the properties whose keys are in K - Omit
removes the properties whose keys are in K - Omit is implemented as Pick
> - Choose Pick or Omit based on which has the smaller key set K
- Neither Pick nor Omit works on nested properties — top-level only
Want to track your progress?
Log in to save your place and pick up where you left off.
Progress track karna chahte ho?
Login karo apni progress save karne ke liye aur jahan chhoda tha wahan se shuru karo.
Login