Gernar
Frontend DeveloperTypeScript

Интервью-вопрос

Что такое Pick в TypeScript

Pick выбирает часть свойств из существующего типа и создает новый тип. На практике это помогает типизировать пропсы, формы и DTO без копирования полей. При этом Pick не фильтрует реальные данные перед сетью, логами или аналитикой.

Добавлен
Редакция

Подготовьте короткий ответ и пару деталей на случай уточняющих вопросов.

🐰0
🥚0

Мини-квиз

Проверка перед разбором

Несколько быстрых вопросов перед разбором. Так проще поймать места, которые только кажутся понятными.

Вопрос 1 из 50 правильно

Как лучше коротко объяснить Pick?

Вы отвечаете на базовый вопрос по TypeScript и хотите не уходить в лишние детали.

Варианты ответа

Разбор

Разобраться, а не зазубрить

Дальше разбираем суть, типичные уточнения и места, где легко сказать лишнее или перепутать термины.

Базовая идея

Pick это встроенный utility type в TypeScript. Он берет исходный тип и список ключей. Затем строит новый тип только с этими ключами.

type User = {
  id: string;
  name: string;
  email: string;
  isAdmin: boolean;
};

type UserPreview = Pick<User, "id" | "name">;

const preview: UserPreview = {
  id: "u1",
  name: "Alex",
};

На интервью можно сказать так. Pick<Type, Keys> выбирает свойства из Type. Keys должен быть ключом или union ключей этого типа. Если написать ключ с ошибкой, TypeScript остановит это на проверке типов.

Что сказать на интервью

Хорошая короткая формулировка может звучать так:

Pick это утилитарный тип TypeScript для создания нового типа из части полей существующего типа. Например, если у меня есть User, но компоненту нужны только id и name, я могу написать Pick<User, "id" | "name">. Так я не дублирую типы полей и сохраняю связь с исходной моделью.

После этого добавьте практический нюанс. Pick не фильтрует реальные данные. Если в объекте есть password, token или внутренняя роль, тип Pick сам по себе не удалит их перед отправкой в API, лог или аналитику.

Как выбрать Pick, Omit или отдельный тип

Как выбрать подход

1Вам нужно описать несколько конкретных полей из большого типа?
Используйте Pick, чтобы не дублировать имена и типы полей.
2Вам нужно взять почти весь тип, кроме пары полей?
Чаще удобнее Omit. Иначе список ключей в Pick быстро разрастется.
3Вам нужен независимый контракт API или формы?
Подумайте об отдельном типе и явном маппере. Pick может слишком сильно связать контракт с доменной моделью, особенно для ответа API, аналитики или данных в localStorage.
4Вам нужно выбрать поля внутри вложенного объекта?
Примените Pick к вложенному типу отдельно. Обычный Pick не работает глубоко.

Выбор зависит не от вкуса, а от границы в коде. Если вы делаете пропсы для маленькой карточки пользователя, Pick часто уместен. Если описываете публичный контракт API, payload формы, событие аналитики или данные для localStorage, отдельный тип и явный маппер могут быть безопаснее.

Сильный ответ показывает этот trade-off. Pick уменьшает дублирование, но усиливает связность. Иногда это плюс, иногда риск.

Практический пример в React

Типичный frontend-сценарий такой. Есть большой тип пользователя, но карточке в списке нужны только несколько полей.

type User = {
  id: string;
  name: string;
  avatarUrl?: string;
  email: string;
  role: "user" | "admin";
};

type UserCardProps = Pick<User, "id" | "name" | "avatarUrl">;

function UserCard({ id, name, avatarUrl }: UserCardProps) {
  return (
    <article>
      {avatarUrl ? <img src={avatarUrl} alt={`Avatar of ${name}`} /> : null}
      <h3>{name}</h3>
      <a href={`/users/${id}`}>Open profile</a>
    </article>
  );
}

Практический плюс такой. Если тип avatarUrl в User изменится, пропсы карточки обновятся вместе с ним. Практический риск тоже есть. Компонент становится связан с User. Если карточка должна показывать не только пользователей, но и авторов из другого API, лучше описать отдельный тип пропсов. Еще один frontend-нюанс. Pick не проверяет, что URL картинки безопасен или что текст подходит для доступности. Это решают в коде компонента и при валидации данных.

Ограничения, которые лучше назвать

Первое ограничение. Pick работает только с типами. Ниже плохой пример, если вы думаете, что так очищаете данные:

type PublicUser = Pick<User, "id" | "name">;

const publicUser = user as PublicUser;
sendAnalytics(publicUser);

Это плохой пример, потому что as PublicUser не удаляет лишние поля из объекта. Если user содержал email, token, password или role, они могут остаться в runtime-объекте и попасть в аналитику или сетевой payload. Безопаснее собрать новый объект явно.

const publicUser: PublicUser = {
  id: user.id,
  name: user.name,
};

Второе ограничение. Pick не делает глубокий выбор.

type User = {
  id: string;
  profile: {
    city: string;
    phone: string;
  };
};

type UserProfile = Pick<User, "profile">;
type UserCity = Pick<User["profile"], "city">;

UserProfile содержит весь объект profile, включая phone. Если потом передать такой объект в дочерний компонент, лог или запрос, лишнее поле останется в данных. Если вам нужен только city, применяйте Pick к User["profile"] и собирайте объект с нужными полями явно.

Практический вывод

На интервью не нужно перечислять все utility types. Лучше показать, что вы понимаете назначение Pick, границы его работы и практические последствия.

Сильный ответ состоит из трех частей. Что делает Pick, где вы применяли бы его во frontend-коде, и чего он не делает. Например, он помогает типизировать пропсы, формы и DTO. Но он не фильтрует реальные данные перед сетью, логами или аналитикой и не выбирает вложенные поля сам.

Частые ошибки

Где обычно ошибаются

Проверьте формулировки, которые звучат уверенно, но на интервью быстро выдают пробелы.

  1. 1

    Думать, что Pick меняет данные в runtime

    Pick работает только на уровне типов. Он не удаляет поля из объекта в JavaScript и не очищает данные перед отправкой на сервер, в аналитику или в localStorage. Так вы можете случайно передать email, token или флаг роли. Если нужно убрать лишние поля на самом деле, соберите новый объект явно.

  2. 2

    Путать Pick и Omit

    Pick выбирает перечисленные поля, а Omit исключает их. Если перепутать эти типы в пропсах или DTO, можно случайно разрешить лишние поля или потерять обязательные данные для UI.

  3. 3

    Ждать глубокий выбор полей

    Pick<User, "profile"> выберет все поле profile, а не отдельные свойства внутри него. Для вложенного выбора используйте Pick<User["profile"], "city"> или отдельный тип.

  4. 4

    Тянуть доменную модель в каждый компонент

    Pick<User, "id" | "name"> удобен для простого компонента, но не всегда подходит для публичного API или сложной формы. Если контракт должен жить отдельно от модели User, лучше назвать его явно и не прятать важную границу за Pick.

Follow-up

Что могут спросить дальше

Короткие ответы на вопросы, где важно показать понимание Pick, keyof и границ TypeScript.

Живые ответы

Видео с похожим вопросом

Если найдем публичные интервью с таким вопросом, добавим их сюда. Их удобно смотреть после теории, чтобы свериться с живыми ответами.

Пока видео нет. Когда появятся подходящие публичные интервью, добавим их в этот блок, чтобы можно было сравнить разбор с тем, как отвечают реальные кандидаты.

Содержание