Utility types — это встроенные инструменты TypeScript для преобразования, модификации или получения производных типов на основе существующих. Наиболее часто встречающиеся:
Partial<T> — делает все свойства типа T необязательнымиRequired<T> — делает все свойства обязательнымиPick<T, K> — выбирает из типа T только свойства KOmit<T, K> — исключает из типа T свойства Ktype User = { id: number; name: string; age?: number }; type UserPreview = Pick<User, 'id' | 'name'>; type UserPatch = Partial<User>; type FullUser = Required<User>; type UserWithoutAge = Omit<User, 'age'>;
Это позволяет создавать более гибкие API и DTO.
Если свойство типа указано как опциональное (
age?: number), как будет вести себя Required<T>? Останется ли оно опциональным?
Ответ: Нет, Required<T> преобразует все свойства типа T, в том числе опциональные, в обязательные (требуемые).
type User = { age?: number }; type UserRequired = Required<User>; // UserRequired: { age: number }
История
Использовали Partial<T> для обновления объектов, считая, что это автоматически безопасно для базы данных. Забыли проверить поля на null/undefined и получили ошибки валидации при апдейте сущностей.
История
Использовали Omit<T, K> для исключения технических свойств из типа запроса, не учтя, что при рефакторинге модели новые технические поля не были добавлены в список исключений. В итоге приватные поля "утекли" наружу через API.
История
В Shared-библиотеке создали тип Pick<T, K>, ошибившись в списке ключей: K частично отсутствовал в оригинальном типе. TypeScript пропустил ошибку при использовании литеральных строк, но при изменении оригинального типа появилось несоответствие, и часть типов "сломалась" во всех сервисах.