← Назад к вопросам

Что делают utility types в TypeScript?

2.0 Middle🔥 241 комментариев
#TypeScript

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Что делают 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 решают три основные задачи:

  1. Переиспользование — создаём новые типы из существующих
  2. Безопасность — гарантируем правильную структуру данных
  3. Удобство — меньше дублирования, больше гибкости

Они особенно полезны при работе с API, формами, и когда нужно создать вариации одного основного типа.