Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Что делают utility types в TypeScript?
Utility types — это встроенные вспомогательные типы TypeScript, которые позволяют трансформировать и создавать новые типы на основе существующих. Они делают код более гибким, переиспользуемым и помогают избежать дублирования типов.
Основные категории utility types
1. Трансформация свойств
Partial<T> — делает все свойства опциональными:
interface User {
name: string;
email: string;
age: number;
}
// Все свойства опциональны
const partialUser: Partial<User> = {
name: "Иван"
// email и age необязательны
};
// Идеально для функций обновления
function updateUser(id: string, updates: Partial<User>) {
// обновляем только переданные свойства
}
Required<T> — делает все свойства обязательными (противоположность Partial):
interface ConfigOptional {
host?: string;
port?: number;
debug?: boolean;
}
// Все свойства теперь обязательны
const config: Required<ConfigOptional> = {
host: "localhost",
port: 3000,
debug: true
};
Readonly<T> — делает все свойства только для чтения:
interface Position {
x: number;
y: number;
}
const pos: Readonly<Position> = { x: 10, y: 20 };
// pos.x = 30; // ❌ Ошибка: Cannot assign to readonly property
2. Выбор и исключение свойств
Pick<T, K> — выбирает только указанные свойства:
interface Product {
id: string;
name: string;
price: number;
description: string;
category: string;
}
// Выбираем только id и name
type ProductPreview = Pick<Product, "id" | "name">;
// { id: string; name: string; }
// Используем для API ответов
function getProductPreview(): ProductPreview {
return { id: "1", name: "Ноутбук" };
}
Omit<T, K> — исключает указанные свойства:
interface User {
id: string;
name: string;
password: string;
email: string;
}
// Исключаем sensitive данные
type PublicUser = Omit<User, "password">;
// { id: string; name: string; email: string; }
function getUserProfile(id: string): PublicUser {
// не возвращаем пароль
}
3. Работа с ключами и значениями
Record<K, T> — создаёт объект с указанными ключами:
type Status = "active" | "inactive" | "pending";
// Объект с ключами Status
const statusMessages: Record<Status, string> = {
active: "Активен",
inactive: "Неактивен",
pending: "В ожидании"
};
// Гарантирует, что все статусы обработаны
function getMessage(status: Status): string {
return statusMessages[status];
}
Exclude<T, U> — исключает типы:
type AllTypes = string | number | boolean | null;
// Исключаем null
type ValidTypes = Exclude<AllTypes, null>;
// string | number | boolean
Extract<T, U> — выбирает только совпадающие типы:
type AllTypes = string | number | boolean | null;
// Выбираем только примитивные типы
type PrimitiveTypes = Extract<AllTypes, string | number>;
// string | number
4. Функциональные типы
Parameters<T> — получает параметры функции:
function createUser(name: string, email: string, age: number) {
// ...
}
type CreateUserParams = Parameters<typeof createUser>;
// [name: string, email: string, age: number]
// Используем для валидации
function validateParams(...args: CreateUserParams) {
// ...
}
ReturnType<T> — получает тип возврата функции:
function fetchUser(): Promise<User> {
// ...
}
type UserData = ReturnType<typeof fetchUser>;
// Promise<User>
5. Условные типы
Awaited<T> — получает тип из Promise:
type PromiseUser = Promise<User>;
type ResolvedUser = Awaited<PromiseUser>;
// User
Практический пример — типизированный API
interface ApiResponse {
id: string;
data: unknown;
timestamp: number;
error?: string;
}
// Успешный ответ без error
type SuccessResponse = Omit<ApiResponse, "error">;
// Только публичные данные
type PublicResponse = Pick<ApiResponse, "id" | "timestamp">;
// Mapping статусов
type RequestStatus = "pending" | "success" | "error";
const statusIcons: Record<RequestStatus, string> = {
pending: "⏳",
success: "✅",
error: "❌"
};
Комбинирование utility types
interface AdminUser {
id: string;
name: string;
email: string;
role: string;
password: string;
permissions: string[];
}
// Комбинируем Omit и Readonly для immutable public профиля
type PublicAdminProfile = Readonly<Omit<AdminUser, "password" | "permissions">>;
// Частичное обновление
type AdminUpdate = Partial<Pick<AdminUser, "name" | "email">>;
Итоги
Utility types решают три основные задачи:
- Переиспользование — создаём новые типы из существующих
- Безопасность — гарантируем правильную структуру данных
- Удобство — меньше дублирования, больше гибкости
Они особенно полезны при работе с API, формами, и когда нужно создать вариации одного основного типа.