Pick and Omit
Instead of creating massive duplicate types for every slight variation of data, TypeScript provides utility types to transform existing shapes.
The problem they solve
In production, you often have a large core entity, but different parts of your application only need a subset of its properties. For example, a database User object might have a password hash, but your public API response should never include it.
Instead of maintaining two separate types and letting them fall out of sync, you derive one from the other.
Pick
Pick<Type, Keys> creates a new type by picking out a specific set of keys from an existing type.
interface User {
id: string;
name: string;
email: string;
passwordHash: string;
role: "admin" | "user";
}
type PublicUser = Pick<User, "id" | "name">;
const user: PublicUser = {
id: "123",
name: "Alice"
// => Adding 'email' here would cause a type error
};
Omit
Omit<Type, Keys> does the exact opposite. It creates a new type by taking all properties from an existing type and removing the specified keys.
type UserUpdatePayload = Omit<User, "id" | "passwordHash">;
const update: UserUpdatePayload = {
name: "Alice New",
email: "alice.new@example.com",
role: "admin"
};
Pick vs Omit — Which one should you use?
Both achieve similar results, but their maintenance profile is inverted.
- Use Omit when you want the new type to automatically inherit new fields added to the base type.
- Use Pick when the new type must strictly be restricted to a known set of fields, regardless of how the base type grows.
If you add createdAt to User, UserUpdatePayload (using Omit) will automatically require it, while PublicUser (using Pick) will ignore it.
Transform types instead of duplicating them. Use
Pickto maintain a strict allowlist of properties, andOmitto maintain a strict blocklist.