Pick<T, K> это встроенный служебный тип, который создаёт объектный тип только из свойств T, названных в K. Используйте его, когда функции или компоненту нужны несколько полей большего типа:
renderPreview принимает и полный User, и обычный объект { id, name }, потому что просит только то, что использует. Такую функцию проще вызывать и тестировать. Pick существует только в типах: во время выполнения у полного объекта ada по-прежнему все пять свойств.
Синтаксис и проверка ключей
Pick<Type, Keys>
Keys это один ключ или объединение ключей, и каждый из них должен существовать в Type. Определение в стандартной библиотеке TypeScript делает это ограничением:
type Pick<T, K extends keyof T> = {
[P in K]: T[P];
};
Благодаря K extends keyof T ключ с опечаткой или отсутствующий ключ это ошибка компиляции, а редактор может автодополнять имена ключей:
Ошибка выглядит так: error TS2344: Type '"cost"' does not satisfy the constraint 'keyof Product'. В этом отличие от Omit, ключи которого не проверяются.
Pick сохраняет readonly и необязательность
Pick перебирает ключи T, поэтому каждое выбранное свойство сохраняет свои модификаторы:
Последняя строка показывает { id: 8 }, потому что readonly это только проверка времени компиляции: о присваивании было сообщено, оно подавлено через @ts-expect-error и всё равно выполнилось. Чтобы изменить модификаторы при выборе, оберните результат: Partial<Pick<Account, "plan">> или Required<Pick<Account, "email">>.
Pick и Omit
Pick называет то, что оставить; Omit называет то, что убрать. Сегодня оба дают одинаковый результат, но ведут себя по-разному, когда исходный тип растёт:
Pick<T, K> | Omit<T, K> | |
|---|---|---|
| Вы перечисляете | ключи, которые оставить | ключи, которые убрать |
Новые свойства в T | не включаются | включаются автоматически |
Неизвестный ключ в K | ошибка компиляции (TS2344) | молча принимается |
| Подходит для | ответов API, публичных представлений, props | «всё, кроме секрета» |
Для данных, покидающих ваш сервер, Pick безопаснее по умолчанию: в типе ничего не появится, если кто-то не добавит это намеренно.
Выбор из вложенных типов
Pick видит только ключи верхнего уровня: путь через точку вроде Pick<Customer, "address.city"> это ошибка (TS2344), а не вложенный выбор. Используйте тип доступа по индексу, чтобы добраться до вложенного типа, а затем выбирайте из него:
Customer["address"] это тип свойства address. Тот же синтаксис добирается до элементов массива: для свойства orders: Order[] тип Customer["orders"][number] это Order.
Типизированная функция pick()
Pick ничего не делает во время выполнения. Небольшая обобщённая функция копирует выбранные свойства в новый объект и возвращает ровно Pick<T, K>:
K extends keyof T позволяет TypeScript вывести K из строковых аргументов, поэтому у типа возврата ровно выбранные ключи. Утверждение {} as Pick<T, K> нужно потому, что у пустого объекта этих свойств ещё нет; цикл их заполняет.
Выбор свойств по типу значения
Pick выбирает по имени ключа. Чтобы выбирать по типу свойства, например «все строковые поля», напишите сопоставленный тип с фильтром ключей:
Конструкция as сопоставляет каждый ключ с самим собой, если его тип подходит, и с never в противном случае, а ключи never отбрасываются. Одна тонкость: тип необязательного свойства включает undefined, поэтому необязательный subtitle?: string здесь не будет считаться string; чтобы включить его, проверяйте на string | undefined.
Часто задаваемые вопросы
Что делает Pick в TypeScript?
Pick<T, K> строит объектный тип, содержащий только те свойства T, ключи которых есть в K. Pick<User, "id" | "name"> это { id: number; name: string }, если у User есть эти два свойства плюс другие. Он работает только с типами и ничего не удаляет из объектов во время выполнения.
Чем Pick отличается от Omit?
Pick перечисляет свойства, которые нужно оставить, Omit те, которые нужно убрать. Когда в исходном типе появляется новое свойство, Omit включает его автоматически, а Pick нет. Pick также проверяет, что его ключи существуют в типе; Omit принимает любой ключ.
Как выбрать несколько свойств в TypeScript?
Передайте объединение ключей: Pick<User, "id" | "name" | "email">. Все ключи должны существовать в User, иначе компилятор сообщит об ошибке TS2344.
Как выбрать вложенное свойство в TypeScript?
Pick выбирает только свойства верхнего уровня. Доберитесь до вложенного типа через тип доступа по индексу и выбирайте из него: Pick<User["address"], "city">. Чтобы сохранить вложенность, сочетайте их: Pick<User, "id"> & { address: Pick<User["address"], "city"> }.
Сохраняет ли Pick модификаторы readonly и необязательности?
Да. Pick это сопоставленный тип по ключам T, поэтому свойство, которое в T было readonly или необязательным, остаётся таким и в выбранном типе.