Skip to content
TypeScript ts utility-types 3 min read

Pick & Omit

Pick and Omit are complementary utility types for carving smaller object types out of larger ones. Pick<T, K> keeps only the named properties, while Omit<T, K> keeps everything except the named properties. Together they let you derive focused view models, DTOs, and form types from a single source of truth instead of hand-writing overlapping interfaces. Both build on the keyof operator and indexed access types.

Pick: keep selected keys

Pick<T, K> constructs a type from T by selecting the set of properties K, where K must be a union of T’s keys. The resulting type has only those properties, with their original modifiers and types intact.

interface User {
  id: number;
  name: string;
  email: string;
  passwordHash: string;
}

type UserPreview = Pick<User, "id" | "name">;
// { id: number; name: string }

const preview: UserPreview = { id: 1, name: "Ada" };

Because K is constrained to keyof T, a typo is caught immediately:

type Bad = Pick<User, "nme">; // ❌ Error: '"nme"' is not assignable to keyof User

Omit: remove selected keys

Omit<T, K> is the mirror image: it constructs a type with all properties of T except those in K. Unlike Pick, the K parameter is loosely typed (string | number | symbol), so unknown keys do not error — a deliberate design choice.

interface User {
  id: number;
  name: string;
  email: string;
  passwordHash: string;
}

type PublicUser = Omit<User, "passwordHash">;
// { id: number; name: string; email: string }

type CreateUser = Omit<User, "id">; // server assigns id

Omit shines when you want “everything but a few sensitive or generated fields”, which is common for API responses and creation payloads.

Because Omit<T, K> does not constrain K to keyof T, a typo like Omit<User, "passwrd"> silently returns the full type. If you need strict key checking, use a custom StrictOmit helper.

How they are built

Pick is a direct mapped type. Omit is defined in terms of Pick plus Exclude:

type MyPick<T, K extends keyof T> = {
  [P in K]: T[P];
};

type MyOmit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;

Reading the Omit definition top-down: take all keys of T, exclude the ones in K, then Pick what remains. This is why Omit’s K is wide — Exclude happily ignores keys that are not present.

Pick vs Omit

AspectPick<T, K>Omit<T, K>
Keepsonly keys in Kall keys except K
K constraintkeyof T (strict)string | number | symbol (loose)
Best whenyou want a few keysyou want most keys
Typo safetyerrors on bad keysilently ignored

Choose whichever expresses intent with the fewest keys: Pick for a small slice, Omit for “all but a couple”.

Composing with other utilities

These compose cleanly with Partial and friends to model real-world payloads:

interface Article {
  id: string;
  title: string;
  body: string;
  authorId: string;
  createdAt: Date;
}

// Create: client supplies content, server generates the rest
type CreateArticle = Omit<Article, "id" | "createdAt">;

// Update: any subset of editable fields
type UpdateArticle = Partial<Omit<Article, "id" | "authorId" | "createdAt">>;

This keeps Article as the single source of truth — change it once and every derived type updates automatically.

Best Practices

  • Derive view models with Pick/Omit instead of duplicating interfaces; the source type stays authoritative.
  • Use Pick when you want a small handful of keys and Omit when you want nearly all of them.
  • Remember Omit’s key argument is not type-checked against T; add a strict helper if accidental typos are a concern.
  • Combine with Partial for update DTOs and with Required for resolved shapes.
  • Keep the union of keys readable — extract a named type Keys = "a" | "b" when reused.
  • Prefer these utilities over re-declaring fields so refactors propagate automatically.
Last updated June 29, 2026
Was this helpful?