Skip to Content
Course content

185: Pick<Type, Keys> and Omit<Type, Keys> Revisited

Click on the "Edit" button in the top corner of the screen to edit your slide content.

I once worked with a developer—let's call him Marcus—who was managing a massive User interface with about 30 different fields. He needed a separate type for the API response that sent user data to the frontend, so he just copied and pasted the User interface into a new one called UserResponse and manually deleted the passwordHash and internalAdminNotes fields. It seemed fine for a week. Then, we added a timezone field to the main User model. Marcus forgot to update UserResponse, and suddenly the frontend was crashing because it expected a timezone that simply wasn't being passed along. This is the "manual synchronization trap," and it's exactly why we use Pick and Omit.

Stripping Sensitive Data with Omit

When you have a "source of truth" type—like a database model—you rarely want to pass that entire object around your application. Most of the time, you want a version of that type that is almost the same, but missing a few sensitive or irrelevant fields. That's where Omit<Type, Keys> shines.

interface UserAccount {
  id: string;
  username: string;
  email: string;
  passwordHash: string;
  lastLoginIp: string;
  createdAt: Date;
}

// Instead of redefining the whole thing, we just say: 
// "Give me everything in UserAccount EXCEPT these two."
type UserProfile = Omit<UserAccount, 'passwordHash' | 'lastLoginIp'>;

const publicProfile: UserProfile = {
  id: 'usr_123',
  username: 'dev_pro',
  email: 'hello@example.com',
  createdAt: new Date(),
  // passwordHash: '...' // This would now trigger a TypeScript error
};

The beauty here is that if I add preferredLanguage to UserAccount tomorrow, UserProfile automatically inherits it. I don't have to hunt through my codebase to update five different "User-like" interfaces.

Creating Lean Views with Pick

While Omit is great for removing a few things, it's often the wrong tool if you only need a tiny fraction of a large object. If your interface has 20 fields and you only need 2, omitting 18 fields is tedious and makes your code harder to read. In those cases, I always reach for Pick<Type, Keys>.

Imagine you're building a user directory. You don't need the full UserProfile for a list of 100 users; you just need their names and avatars. Using Pick allows you to be explicit about what your component actually depends on.

interface UserAccount {
  id: string;
  username: string;
  email: string;
  passwordHash: string;
  avatarUrl: string;
  bio: string;
  location: string;
}

// We only want a small slice of the data for the directory list
type UserDirectoryItem = Pick<UserAccount, 'username' | 'avatarUrl'>;

function UserAvatar({ user }: { user: UserDirectoryItem }) {
  return `<img src="${user.avatarUrl}" alt="${user.username}" />`;
}

I personally find that Pick is a great way to document your intentions. When another engineer looks at UserDirectoryItem, they immediately know exactly which pieces of the user object are being used in that specific context, without having to guess what was "left over" from an Omit.




📋 Practical Task

Refactoring the Product Management API

You are working on an e-commerce backend. You have a central Product interface, but you've noticed that the team is manually creating duplicate interfaces for different API endpoints, leading to bugs. Your task is to refactor these using Pick and Omit.

interface Product {
  id: string;
  sku: string;
  name: string;
  description: string;
  price: number;
  costPrice: number; // Sensitive: should not be sent to customers
  stockQuantity: number;
  category: string;
  imageUrl: string;
  createdAt: Date;
  updatedAt: Date;
}

// 1. Create a type 'ProductPublicView' that includes everything 
//    EXCEPT 'costPrice' and 'stockQuantity'.
type ProductPublicView = // Your code here

// 2. Create a type 'ProductThumbnail' that ONLY includes 
//    'id', 'name', and 'imageUrl'.
type ProductThumbnail = // Your code here

// 3. Create a type 'ProductUpdateInput' that allows updating 
//    anything EXCEPT the 'id', 'sku', and 'createdAt' fields.
type ProductUpdateInput = // Your code here
Rating
0 0

There are no comments for now.

to be the first to leave a comment.