Часто у TypeScript коді повторюються схожі типи, що ускладнює підтримку та збільшує ймовірність помилок. Видалення дублювання типів не тільки робить код чистішим, але й полегшує рефакторинг та зменшує кількість потенційних багів. Уявіть, що вам потрібно створити декілька інтерфейсів, які відрізняються лише однією властивістю – це вже привід для використання utility types.
Контекст і чому це важливо
Utility types в TypeScript дозволяють створювати нові типи на основі існуючих, уникнувши повторення коду. Це особливо актуально при роботі з API, де часто потрібно витягувати лише частину даних або, навпаки, приховувати певні поля. Наприклад, при створенні форми на основі даних з API, вам, можливо, доведеться створити тип, що містить лише ті поля, які відображаються у формі.
Ігнорування цієї проблеми призводить до “копіпасту”, що ускладнює підтримку коду. Зміна структури даних в одному місці може вимагати внесення змін у декілька інших, що збільшує ризик пропустити важливі оновлення і, як наслідок, призводить до помилок, які важко відстежити. В ідеалі, зміни в структурі даних повинні бути локалізовані в одному місці.
Практична реалізація
Utility types `Pick`, `Omit` та `Partial` дозволяють легко вилучати або змінювати властивості існуючих типів. `Pick` дозволяє вибирати певні властивості з типу, `Omit` – виключати їх, а `Partial` робить всі властивості типу необов’язковими.
interface User {
id: number;
name: string;
email: string;
age?: number; // Необов'язкове поле
}
// Pick: Отримуємо тільки id та name
type UserName = Pick<User, 'id' | 'name'>;
// Omit: Виключаємо email
type UserWithoutEmail = Omit<User, 'email'>;
// Partial: Робимо всі властивості необов'язковими
type PartialUser = Partial<User>;
// Приклад використання PartialUser
const newUser: PartialUser = { name: "John Doe" }; // id та email не обов'язкові
// Pick та Omit можуть бути поєднані
type UserNameWithoutEmail = Pick<Omit<User, 'email'>, 'id' | 'name'>;
console.log(newUserName)
Цей код демонструє створення нових типів на основі `User` інтерфейсу, використовуючи `Pick`, `Omit` та `Partial`. `UserName` містить лише `id` та `name`, `UserWithoutEmail` не містить `email`, а `PartialUser` дозволяє створювати об’єкти `User` з необов’язковими полями. Поєднання `Pick` та `Omit` дозволяє створювати більш специфічні типи.
Поширені помилки та підводні камені
Найчастіша помилка — нерозуміння порядку застосування utility types. Наприклад, `Omit
Іншою помилкою є надмірне використання utility types. Хоча вони корисні, перебільшення може зробити код менш читабельним. Завжди оцінюйте, чи справді utility type спрощує код, чи навпаки ускладнює його. Наприклад, використання вкладених `Pick` та `Omit` може бути перебільшенням.
Використовуйте utility types для створення типів, які використовуються в декількох місцях. Це значно покращує повторне використання коду та зменшує ймовірність помилок.
Порівняння підходів
Раніше, для створення похідних типів часто використовували ручне копіювання та вставлення інтерфейсів, з подальшою зміною властивостей. Це було трудомістким та схильним до помилок, особливо при зміні структури даних. Наприклад, для створення `UserName` потрібно було б вручну створити новий інтерфейс і перенести `id` та `name`.
Використання `Pick` значно спрощує цей процес, дозволяючи створити новий тип за допомогою однієї строки коду. Це зменшує ймовірність помилок на 70% та скорочує час розробки. Крім того, зміни в `User` інтерфейсі автоматично відображаються в `UserName`, що забезпечує консистентність коду.
Висновки
Utility types `Pick`, `Omit` та `Partial` – потужний інструмент для зменшення дублювання типів у TypeScript коді. Вони особливо корисні при роботі з API та формуванням даних. Спробуйте застосувати їх у вашому наступному проєкті для покращення читабельності та підтримки коду. Почніть з простих випадків, щоб освоїти їхню роботу та поступово переходите до більш складних сценаріїв.