Какие использовал utility type?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Моё практическое применение Utility Types в TypeScript
За годы разработки на TypeScript я активно использую utility types — они стали неотъемлемой частью моего workflow для создания типобезопасных, гибких и поддерживаемых кодовых баз. Вот ключевые категории и примеры их применения:
Базовые utility types для манипуляции типами
Partial<T> — создаю, когда нужно временно ослабить требования к объекту, особенно полезно в формах и постепенном обновлении данных:
interface User {
id: number;
name: string;
email: string;
age?: number;
}
// Для формы редактирования, где поля заполняются постепенно
type UserUpdateForm = Partial<User>;
const updateData: UserUpdateForm = {
name: "Новое имя"
// email и id не обязательны здесь
};
Required<T> — противоположность Partial, использую когда нужно гарантировать заполнение всех полей, даже optional:
type StrictUser = Required<User>;
// Теперь age тоже обязателен
Readonly<T> и ReadonlyArray<T> — для иммутабельности, критически важны в Redux-редьюсерах и конфигурационных объектах:
interface Config {
apiUrl: string;
timeout: number;
}
const appConfig: Readonly<Config> = {
apiUrl: "https://api.example.com",
timeout: 5000
};
// appConfig.apiUrl = "new" // Ошибка компиляции!
Утилиты для работы с ключами и значениями
Pick<T, K> и Omit<T, K> — использую ежедневно для композиции типов:
// Выбираю только нужные поля для компонента
type UserPreview = Pick<User, "id" | "name">;
// Исключаю чувствительные данные перед отправкой на клиент
type SafeUser = Omit<User, "password" | "refreshToken">;
// Практический пример в React-компоненте:
interface UserCardProps extends Pick<User, "name" | "email"> {
avatarUrl: string;
onSelect?: () => void;
}
Record<K, T> — для типобезопасных словарей и маппингов:
// Типизация темы оформления
type ColorPalette = Record<"primary" | "secondary" | "error", string>;
// Конфигурация роутов
type Routes = Record<string, {
path: string;
component: React.ComponentType;
}>;
Продвинутые utility types для сложных сценариев
Exclude<T, U> и Extract<T, U> — для работы с union-типами:
type Status = "pending" | "success" | "error" | "idle";
type FinalStatus = Exclude<Status, "idle">; // "pending" | "success" | "error"
type ResultStatus = Extract<Status, "success" | "error">; // "success" | "error"
NonNullable<T> — очистка от null и undefined:
type MaybeString = string | null | undefined;
type DefiniteString = NonNullable<MaybeString>; // string
Parameters<T> и ReturnType<T> — для работы с функциями, особенно в HOC и утилитах:
function fetchUser(id: number, options?: { cache: boolean }): Promise<User> {
// реализация
}
type FetchUserParams = Parameters<typeof fetchUser>; // [number, { cache: boolean }?]
type UserPromise = ReturnType<typeof fetchUser>; // Promise<User>
// Практическое применение - создание типизированных декораторов
function withLogging<T extends (...args: any[]) => any>(
fn: T
): (...args: Parameters<T>) => ReturnType<T> {
return (...args) => {
console.log(`Calling ${fn.name} with:`, args);
return fn(...args);
};
}
Собственные utility types на основе встроенных
В крупных проектах создаю кастомные utility types:
// Deep Partial для вложенных объектов
type DeepPartial<T> = {
[P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P];
};
// Тип для значений объекта
type ValueOf<T> = T[keyof T];
// Утилита для nullable полей в формах
type FormFields<T> = {
[K in keyof T]: T[K] | null;
};
Практические паттерны применения
- API-слои и DTO — использую
Pick,Omitдля трансформации типов между слоями приложения - Состояние форм —
Partial,Requiredдля валидации и управления состоянием - Конфигурация —
Readonlyдля объектов, которые не должны изменяться - Полиморфные компоненты —
Extract,Excludeдля conditional props - Тестирование —
Parametersдля типизации моков и стабов
Utility types в TypeScript — это мощный инструмент для создания самодокументируемого кода, который предотвращает целые классы ошибок на этапе компиляции. Их правильное использование значительно снижает cognitive load при работе с большими кодовыми базами и улучшает developer experience всей команды.