Pick<Type, Keys>

Constructs a type from Type keeping only the named properties.

Signature
type Pick<Type, Keys extends keyof Type> = { [Property in Keys]: Type[Property] }
  • Added in TypeScript 2.1

Parameters

ParameterTypeDescription
$Typeany typeThe source type to project from.
$Keyskeyof Type (a key or union of keys of Type)The property keys to keep. Constrained to `keyof Type`, so a key that does not exist on Type is a compile error.

Return value

An object type containing only the properties named in KeysA mapped type over Keys where each property keeps its original type from Type, including optionality and readonly modifiers.

Errors

A key in Keys that is not assignable to `keyof Type` fails the constraint: "Type '"x"' does not satisfy the constraint 'keyof Type'".

Changelog

  • PHP 3.5`Omit` was added to the standard library as `Pick<T, Exclude<keyof T, K>>`, making the two the standard subtractive/additive pair.

Pick builds a new object type from an existing one by keeping the properties you name. Property types, optionality and readonly modifiers all carry over untouched.

When to reach for it

  • Projections. A list endpoint returns Pick<User, "id" | "name"> while the detail endpoint returns the whole User. The two stay in sync automatically.
  • Narrow function parameters. A function that only reads id and status should say so: function summarise(order: Pick<Order, "id" | "status">). Callers can pass a full Order, and the signature documents exactly what is touched.
  • Component props. Forward a subset of a model's fields without redeclaring their types.

Pick versus Omit

They are two views of the same operation — Omit is literally defined as Pick<Type, Exclude<keyof Type, Keys>>. Choose Pick when the kept set is small and stable, and Omit when the removed set is. The practical difference is what happens when the source type grows a field: a Pick ignores it, an Omit silently includes it.

What trips people up

Keys is constrained to keyof Type, so typos are caught — unlike Omit. And Pick is not deep: picking an object-valued property gives you the whole nested object.

Example

Try it yourself
Loading editor…
Press Run to execute the code.

When to use it

  • Define a list-view DTO as a projection of the full model type.
  • Declare a function parameter as only the fields the function actually reads.
  • Build a form's value type from the subset of model fields the form edits.

Frequently asked questions

How do I create a type with only some properties of an interface?

Use `Pick<T, "a" | "b">` — it maps over the named keys and copies each property's type, optionality and readonly modifier from the source.

What is the difference between Pick and Omit?

`Pick` names the properties to keep, `Omit` names the ones to remove — and `Omit` is literally implemented as `Pick<T, Exclude<keyof T, K>>`. The practical difference is that `Pick` is constrained to real keys of `T` while `Omit` accepts any key.

Does Pick keep optional and readonly modifiers?

Yes. Homomorphic mapped types like `Pick` preserve the `?` and `readonly` modifiers of each property they copy, so an optional field stays optional.

More examples

A parameter that declares exactly what it reads

Prints `ord_9 [shipped]` then `ord_10 [pending]`. Both calls type-check: the full `Order` is assignable to the picked type because it has at least those properties, and the two-key literal is assignable because it has exactly them. Tests can now construct the tiny object instead of a whole fixture.

Example · typescript
interface Order {
  id: string;
  customerId: string;
  status: "pending" | "shipped" | "cancelled";
  lineItems: { sku: string; qty: number }[];
  internalNotes: string;
}

// The signature promises this function never sees notes or line items.
function badge(order: Pick<Order, "id" | "status">): string {
  return `${order.id} [${order.status}]`;
}

const full: Order = {
  id: "ord_9",
  customerId: "cus_1",
  status: "shipped",
  lineItems: [{ sku: "A1", qty: 2 }],
  internalNotes: "call before delivery",
};

console.log(badge(full));                          // a full Order is accepted
console.log(badge({ id: "ord_10", status: "pending" })); // so is the minimum

Pick and Omit over the same interface

The two logs show the halves of the same record: `{ email: '[email protected]', passwordHash: '9f3c' }` and `{ id: 1, name: 'Ada', email: '[email protected]' }`. Note that `Omit<User, "passwordHash">` and the rest-destructuring line up exactly — that pairing is why rest destructuring is the idiomatic runtime companion to `Omit`.

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

type Credentials = Pick<User, "email" | "passwordHash">;
type SafeUser = Omit<User, "passwordHash">;

const record: User = {
  id: 1,
  name: "Ada",
  email: "[email protected]",
  passwordHash: "9f3c",
};

const creds: Credentials = {
  email: record.email,
  passwordHash: record.passwordHash,
};

const { passwordHash, ...safe } = record;
const forClient: SafeUser = safe;

console.log(creds);
console.log(forClient);

Discussion

  • Be the first to comment on this lesson.