Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI2 апр. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Для чего нужен Pick в TypeScript
Pick - это utility type для создания нового типа, выбирая только определённые поля из существующего типа. Это полезно для переиспользования типов и избежания дублирования кода.
Базовое использование
interface User {
id: string;
name: string;
email: string;
password: string;
phone?: string;
address?: string;
age?: number;
}
// Создаём новый тип, выбирая только нужные поля
type UserPreview = Pick<User, 'id' | 'name'>;
// Это эквивалентно:
interface UserPreview {
id: string;
name: string;
}
const user: UserPreview = {
id: '123',
name: 'John'
};
Практические примеры
1. Публичный профиль (без приватных данных)
interface User {
id: string;
name: string;
email: string;
password: string; // Не нужна в публичном профиле
phone: string;
isAdmin: boolean; // Не нужно показывать
}
// Профиль для API ответа
type UserPublicProfile = Pick<User, 'id' | 'name' | 'phone'>;
// Использование
function getUserProfile(userId: string): UserPublicProfile {
const user = getUser(userId);
return {
id: user.id,
name: user.name,
phone: user.phone
};
}
2. Форма редактирования (только редактируемые поля)
interface Article {
id: string; // readonly
title: string;
content: string;
author: string; // readonly
createdAt: Date; // readonly
updatedAt: Date; // readonly
tags: string[];
published: boolean;
}
// Только те поля, которые можно редактировать
type ArticleEditForm = Pick<Article, 'title' | 'content' | 'tags' | 'published'>;
function updateArticle(id: string, data: ArticleEditForm) {
// data содержит только редактируемые поля
}
3. API запрос (только нужные поля)
interface CreateUserRequest {
email: string;
password: string;
name: string;
phone?: string;
}
interface User extends CreateUserRequest {
id: string;
createdAt: Date;
isActive: boolean;
}
// Используем Pick для переиспользования типа
type UserCreateData = Pick<User, 'email' | 'password' | 'name' | 'phone'>;
// Или проще
type UserCreateData = Omit<User, 'id' | 'createdAt' | 'isActive'>;
4. React компоненты - передача части props
interface ButtonProps {
onClick: () => void;
disabled?: boolean;
loading?: boolean;
variant?: 'primary' | 'secondary';
size?: 'small' | 'medium' | 'large';
children: React.ReactNode;
className?: string;
title?: string;
ariaLabel?: string;
}
// Для простых кнопок передаём только базовые props
type SimpleButtonProps = Pick<ButtonProps, 'onClick' | 'disabled' | 'children'>;
function SimpleButton(props: SimpleButtonProps) {
return <button onClick={props.onClick} disabled={props.disabled}>{props.children}</button>;
}
// Для кнопки с полным функционалом используем все props
function AdvancedButton(props: ButtonProps) {
return (
<button
onClick={props.onClick}
disabled={props.disabled || props.loading}
className={`btn btn-${props.variant} btn-${props.size}`}
title={props.title}
aria-label={props.ariaLabel}
>
{props.loading ? 'Loading...' : props.children}
</button>
);
}
Pick vs Omit
Pick - выбираешь что ВКЛЮЧИТЬ Omit - выбираешь что ИСКЛЮЧИТЬ
interface Product {
id: string;
name: string;
description: string;
price: number;
inStock: boolean;
inventory: number;
warehouse: string;
supplier: string;
createdAt: Date;
}
// Pick - для простого типа берём основные поля
type ProductCard = Pick<Product, 'id' | 'name' | 'price' | 'inStock'>;
// Omit - когда мало исключаемых полей
type ProductForDisplay = Omit<Product, 'inventory' | 'warehouse' | 'supplier' | 'createdAt'>;
// Результат один и тот же
const product1: ProductCard = { id: '1', name: 'Item', price: 100, inStock: true };
const product2: ProductForDisplay = { id: '1', name: 'Item', description: 'Desc', price: 100, inStock: true };
С функциями
interface User {
id: string;
name: string;
email: string;
password: string;
role: 'admin' | 'user';
}
// Функция берёт только нужные поля
function sendWelcomeEmail(user: Pick<User, 'email' | 'name'>) {
console.log(`Sending email to ${user.name} at ${user.email}`);
}
const user: User = {
id: '1',
name: 'John',
email: 'john@example.com',
password: 'secret',
role: 'user'
};
sendWelcomeEmail(user); // OK, Pick только требует email и name
// Функция явно говорит, что ей нужны только эти два поля
// Если в будущем удалим name, функция сломается (хорошо!)
С конструктором объектов
interface FullUser {
id: string;
firstName: string;
lastName: string;
email: string;
phone: string;
address: string;
}
class UserService {
// Создание пользователя требует только определённые данные
create(data: Pick<FullUser, 'firstName' | 'lastName' | 'email'>) {
// id и остальные поля генерируются сервером
return {
id: generateId(),
...data,
phone: '',
address: ''
};
}
// Обновление - разные поля
update(id: string, data: Pick<FullUser, 'firstName' | 'lastName' | 'phone'>) {
// email и address не меняются
}
}
Комбинирование Pick с другими типами
interface Article {
id: string;
title: string;
content: string;
author: string;
tags: string[];
published: boolean;
views: number;
}
// Комбинируем Pick с расширением
type ArticlePreview = Pick<Article, 'id' | 'title' | 'author'> & {
excerpt: string; // Добавляем новое поле
readTime: number;
};
const preview: ArticlePreview = {
id: '1',
title: 'Article',
author: 'John',
excerpt: 'First 100 chars...',
readTime: 5
};
// Или с Partial для опциональных полей
type ArticleUpdateData = Partial<Pick<Article, 'title' | 'content' | 'tags' | 'published'>>;
const updateData: ArticleUpdateData = {
title: 'New Title'
// Остальные поля опциональны
};
Реальный пример: OAuth
interface OAuthUser {
id: string;
email: string;
name: string;
avatar: string;
provider: 'google' | 'github' | 'facebook';
accessToken: string; // Приватная информация
refreshToken: string; // Приватная информация
expiresAt: Date; // Приватная информация
}
// Публичная информация пользователя
type PublicUserInfo = Pick<OAuthUser, 'id' | 'email' | 'name' | 'avatar'>;
function getPublicProfile(user: OAuthUser): PublicUserInfo {
return {
id: user.id,
email: user.email,
name: user.name,
avatar: user.avatar
};
}
function storeTokens(user: OAuthUser): Pick<OAuthUser, 'accessToken' | 'refreshToken'> {
return {
accessToken: user.accessToken,
refreshToken: user.refreshToken
};
}
Вывод
Pick используется для:
- Переиспользования типов - выбираешь нужные поля существующего типа
- Безопасности - скрываешь приватные данные в public API
- Ясности - функция явно показывает, какие данные ей нужны
- Поддерживаемости - если структура тип меняется, Pick автоматически адаптируется
- DRY принципу - не дублируешь определение одних и тех же полей
Правило: Если видишь дублирование полей в разных типах - используй Pick для переиспользования существующего типа.