Приведи пример утилитарных типов в TypeScript
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Примеры утилитарных типов в TypeScript
Утилитарные типы (Utility Types) в TypeScript — это встроенные обобщённые типы, которые позволяют преобразовывать существующие типы более удобным и декларативным способом. Они существенно упрощают работу со сложными типами, делая код более выразительным и безопасным. Вот основные категории и примеры.
1. Типы для модификации свойств объекта
Partial<T>
Создаёт тип, где все свойства T становятся необязательными.
interface User {
id: number;
name: string;
email: string;
}
type PartialUser = Partial<User>;
// Эквивалентно: { id?: number; name?: string; email?: string; }
function updateUser(user: User, updates: PartialUser): User {
return { ...user, ...updates }; // Можно передать только часть полей
}
Required<T>
Делает все свойства T обязательными (убирает ?).
interface Config {
apiUrl?: string;
timeout?: number;
}
type StrictConfig = Required<Config>;
// Эквивалентно: { apiUrl: string; timeout: number; }
Readonly<T>
Делает все свойства T доступными только для чтения.
interface State {
count: number;
}
const state: Readonly<State> = { count: 0 };
// state.count = 1; // Ошибка: свойство только для чтения
2. Типы для трансформации ключей
Record<K, T>
Создаёт тип объекта с ключами типа K и значениями типа T.
type PageUrls = Record<'home' | 'about' | 'contact', string>;
// Эквивалентно: { home: string; about: string; contact: string; }
const urls: PageUrls = {
home: '/',
about: '/about',
contact: '/contact'
};
Pick<T, K>
Выбирает из типа T только указанные ключи K.
interface Product {
id: number;
name: string;
price: number;
description: string;
}
type ProductPreview = Pick<Product, 'id' | 'name' | 'price'>;
// Эквивалентно: { id: number; name: string; price: number; }
Omit<T, K>
Исключает из типа T указанные ключи K.
type ProductWithoutPrice = Omit<Product, 'price' | 'description'>;
// Эквивалентно: { id: number; name: string; }
3. Типы для работы с функциями и их параметрами
ReturnType<T>
Извлекает тип возвращаемого значения функции.
function fetchData(): Promise<{ data: string }> {
return Promise.resolve({ data: 'result' });
}
type FetchResult = ReturnType<typeof fetchData>;
// Эквивалентно: Promise<{ data: string }>
Parameters<T>
Извлекает кортеж типов параметров функции.
function createUser(name: string, age: number, isActive: boolean) {
return { name, age, isActive };
}
type CreateUserParams = Parameters<typeof createUser>;
// Эквивалентно: [name: string, age: number, isActive: boolean]
4. Условные типы и манипуляции со строками
Exclude<T, U>
Исключает из T все типы, которые можно присвоить U.
type AllEvents = 'click' | 'scroll' | 'mousemove';
type MouseEvents = Exclude<AllEvents, 'scroll'>;
// Эквивалентно: 'click' | 'mousemove'
Extract<T, U>
Извлекает из T все типы, которые можно присвоить U.
type PossibleValues = string | number | boolean;
type OnlyStrings = Extract<PossibleValues, string>;
// Эквивалентно: string
NonNullable<T>
Удаляет null и undefined из типа T.
type MaybeString = string | null | undefined;
type DefinitelyString = NonNullable<MaybeString>;
// Эквивалентно: string
5. Практический пример комбинации утилитарных типов
// Исходный тип
interface ApiResponse {
status: number;
data: {
users: Array<{
id: number;
name: string;
email: string;
role: 'admin' | 'user';
}>;
meta: {
page: number;
total: number;
};
};
error?: string;
}
// 1. Создаём тип для обновления пользователя (все поля необязательны, кроме id)
type UserUpdate = Pick<ApiResponse['data']['users'][0], 'id'> &
Partial<Omit<ApiResponse['data']['users'][0], 'id'>>;
// 2. Тип только для данных успешного ответа
type SuccessResponse = Omit<NonNullable<ApiResponse>, 'error'>;
// 3. Тип для ключей пользователя (без методов)
type UserKeys = keyof ApiResponse['data']['users'][0];
// Эквивалентно: 'id' | 'name' | 'email' | 'role'
// Использование
function processResponse(response: SuccessResponse): void {
console.log(`Page ${response.data.meta.page} of ${response.data.meta.total}`);
}
const update: UserUpdate = { id: 1, name: 'New Name' }; // email и role не обязательны
Выводы
Утилитарные типы TypeScript предоставляют мощный инструментарий для:
- Создания производных типов без дублирования кода
- Повышения типобезопасности при работе с частичными данными
- Извлечения и преобразования сложных типов
- Создания более гибких и поддерживаемых API
Их грамотное использование позволяет писать более декларативный и надёжный код, минимизировать ошибки типизации и улучшать разработку за счёт автодополнения и проверок на этапе компиляции. В современных проектах TypeScript они стали неотъемлемой частью повседневной разработки, особенно при работе с REST API, конфигурациями и сложными предметными областями.