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

Что такое утилитные типы данных?

2.0 Middle🔥 141 комментариев
#JavaScript Core

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

🐱
deepseek-v3.2PrepBro AI7 апр. 2026 г.(ред.)

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

Что такое утилитные типы в TypeScript

Утилитные типы (Utility Types) — это встроенные в TypeScript обобщённые типы, которые позволяют преобразовывать существующие типы в новые, часто с меньшим количеством ручного кодирования. Они являются "утилитами" в буквальном смысле — инструментами для более гибкой и безопасной работы с системой типов, особенно при использовании дженериков и сложных структур данных.

Ключевые примеры утилитных типов

TypeScript предоставляет множество встроенных утилитных типов. Рассмотрим основные:

Partial<T>

Создаёт тип, в котором все свойства T становятся необязательными:

interface User {
    id: number;
    name: string;
    email: string;
}

// Все свойства теперь optional
type PartialUser = Partial<User>;
// Эквивалентно: { id?: number; name?: string; email?: string; }

function updateUser(id: number, updates: PartialUser) {
    // Можно передать только изменяемые поля
}

Required<T>

Противоположность Partial — делает все свойства обязательными:

interface Config {
    apiUrl?: string;
    timeout?: number;
}

type StrictConfig = Required<Config>;
// Теперь и apiUrl, и timeout обязательны

Readonly<T>

Делает все свойства типа доступными только для чтения:

interface State {
    count: number;
    user: string;
}

type ImmutableState = Readonly<State>;
const state: ImmutableState = { count: 0, user: 'John' };
// state.count = 1; // Ошибка: свойство только для чтения

Pick<T, K> и Omit<T, K>

Позволяют выбирать или исключать свойства из типа:

interface Product {
    id: number;
    name: string;
    price: number;
    description: string;
    category: string;
}

// Выбираем только нужные свойства
type ProductPreview = Pick<Product, 'id' | 'name' | 'price'>;

// Исключаем ненужные свойства
type ProductWithoutDescription = Omit<Product, 'description'>;

Почему утилитные типы важны

  1. DRY принцип (Don't Repeat Yourself): Утилитные типы позволяют избежать дублирования определений типов. Вместо создания нового интерфейса с похожими свойствами можно преобразовать существующий.

  2. Типобезопасность: Они обеспечивают безопасность типов при работе с частичными данными, например, при обновлении объектов:

// Без Partial пришлось бы делать так:
interface UserUpdate {
    id?: number;
    name?: string;
    email?: string;
}

// С Partial код становится чище и синхронизируется с основным типом
function patchUser(user: Partial<User>) {
    // Типобезопасное обновление
}
  1. Гибкость при композиции: Утилитные типы можно комбинировать для создания сложных преобразований:
// Создаём тип для формы редактирования
type EditableProduct = Partial<Pick<Product, 'name' | 'price'>> & {
    id: number; // id обязательно
};

Расширенные сценарии использования

Утилитные типы особенно мощны в сочетании с условными типами и дженериками:

// Кастомный утилитный тип для извлечения типа возвращаемого значения функции
type ReturnType<T> = T extends (...args: any[]) => infer R ? R : never;

function getUser() { return { id: 1, name: 'John' }; }
type UserReturnType = ReturnType<typeof getUser>; // { id: number; name: string; }

Практические рекомендации

  • Используйте Partial для параметров обновления объектов
  • Применяйте Readonly для иммутабельных конфигураций
  • Используйте Pick/Omit для создания view-моделей или DTO
  • Комбинируйте утилитные типы для сложных преобразований
  • Создавайте собственные утилитные типы для повторяющихся паттернов в проекте

Утилитные типы — это не просто синтаксический сахар, а фундаментальная часть системы типов TypeScript, которая позволяет создавать более выразительные, безопасные и поддерживаемые кодовые базы. Они особенно ценны в крупных проектах, где важны согласованность типов и минимальное дублирование.

Что такое утилитные типы данных? | PrepBro