TypeScript: вибрані властивості необов’язкові з Partial & Omit
Коли ви використовуєте утиліту Partial
для типу, вона зробить усі властивості типу необов’язковими. Давайте подивимося, як ми можемо поєднати цю утиліту з іншою Omit
, щоб зробити необов’язковими лише певні властивості цього типу. Нарешті ми створимо тип утиліти, використовуючи генерики TypeScript, щоб застосувати це до будь-якого типу, який ми хочемо.
Зробити всі властивості типу необов’язковими
Утиліти та Partial
добре Omit
відомі у сфері TypeScript, тому що вони дуже зручні, щоб швидко застосувати їх до типу та отримати, по суті, новий тип. Partial<T>
перетворить усі ключі типу на необов’язкові. Якщо, наприклад, у вас такий тип:
interface Band {
lead: string
guitar: string
bass: string
drums: string
keyboard: string
}
усі властивості потрібні, якщо щось має цей тип. Якщо ви хочете призначити такий об’єкт:
const FooFighters: Band = {
lead: 'Dave Grohl',
guitar: 'Pat Smears',
bass: 'Nate Mendel',
drums: 'Taylor Williams',
}
це не вдасться, оскільки в ньому відсутня keyboard
властивість. Тепер ми можемо позначити цю властивість як необов’язкову, і TypeScript легко дозволяє нам це зробити. Найпростіший спосіб зробити це, додавши знак питання до його імені. У цьому випадку, якщо можна редагувати вихідний тип, ви можете перейти до нього та змінити його таким чином:
interface Band {
lead: string
guitar: string
bass: string
drums: string
keyboard?: string
}
чудово Тепер попереднє призначення буде виконано успішно, оскільки keyboard
більше не потрібно. Але що, якщо з будь-якої причини неможливо змінити вихідний тип? Що ви можете швидко зробити в цих випадках, це застосувати Partial
до цього типу:
type NotAllTheBand = Partial
const FooFighters: NotAllTheBand = {
lead: 'Dave Grohl',
guitar: 'Pat Smears',
bass: 'Nate Mendel',
drums: 'Taylor Williams',
}
Це припиняє виконання всіх властивостей, роблячи їх необов’язковими. Можливо, іноді ми хочемо цього, але що, якщо ми просто хочемо зробити лише одну властивість необов’язковою та не змінювати вихідний тип?
Видалення властивостей із типу
Перш ніж ми перейдемо до нього та подивимося, як він працює, давайте подивимось іншу утиліту, яка допоможе нам у цьому: Omit
. Цей тип утиліти видаляє властивості з типу, до якого він застосований. Хоча Partial
не приймає інших аргументів, крім типу, Omit
приймає тип і властивості, які потрібно видалити: Omit<T, K>
.
Це не Partial
робить їх необов’язковими: Omit
повністю видалить їх із типу. Коли ви використовуєте Partial<Band>
, це ніби ви зробили це:
interface Band {
lead?: string
guitar?: string
bass?: string
drums?: string
keyboard?: string
}
Однак, коли ви використовуєте Omit<Band, 'keyboard'>
, це ніби ви зробили це:
interface Band {
lead: string
guitar: string
bass: string
drums: string
}
Тепер це починає мати сенс, чи не так? Чи можете ви уявити, що ми могли б зробити в TypeScript, якщо у нас є тип, який має всі властивості оригінального, встановлені як необов’язкові, і інший тип, який має лише властивості, які ми хочемо вимагати? Якби тільки був спосіб… перетинати ці типи, чи не так?
Пересічні типи
Так, у TypeScript є спосіб використання амперсанда &
, оператора перетину типів. Цей оператор, маючи два типи, створює новий з властивостями, які належать до обох типів:
interface SomeType {
propA: string
propB: number
}
interface AnotherType {
propC: boolean
propD: Array
}
type IntersectedType = SomeType & AnotherType
Тепер ви, мабуть, зрозуміли: ми збираємося перетнути частковий тип і тип, де ми видалили деякі його властивості.
Зробити вибрані властивості типу необов’язковими
Спробуємо розібратися в цьому. Під час вивчення TypeScript важливо раціонально розуміти, що відбувається з нашими типами.
Ми візьмемо тип, усі властивості якого встановлено як необов’язкові завдяки Partial
застосуванню до нього. Далі ми збираємося перетнути його з типом, який вилучив вибрані властивості Omit
. Давайте подивимося на приклад:
interface SomeType {
propA: string
propB: number
}
type OptionalPropB = Partial & Omit
Тепер у нас є новий тип без змін оригінального типу, який виглядає так:
type OptionalPropB = {
propA: string
propB?: string
}
Це відбувається тому, що ми захоплюємо властивості propA?
і propB?
з типу, створеного, Partial
і перетинаємо їх із propA
типом, створеним Omit
.
Загальні утиліти TypeScript
Гаразд, тепер наш новий тип працює, і ми можемо мати лише вибрані властивості, позначені як необов’язкові, не змінюючи вихідний тип. Проте ця лінія
type OptionalPropB = Partial & Omit
Надто багатослівний, досить некрасивий і нудний, щоб писати кожного разу. Що ще важливіше, це не працюватиме для іншого типу, нам доведеться щоразу писати його знову. Чи можемо ми зробити його коротшим і красивішим і підійти для будь-якого типу? Так, TypeScript дозволяє нам використовувати тут універсали та створювати власний тип утиліти:
type Optional = Partial & Omit
І тепер у нас є власний тип утиліти TypeScript, реалізований за допомогою генериків, які ми можемо використовувати, щоб зробити властивості вибраного типу необов’язковими для будь-якого типу. Ми можемо використовувати це так:
type TypeWithOptionalProp = Optional
Ви помітите, що підпис подібний до Omit: ця утиліта приймає тип, з яким потрібно працювати, і властивості, які будуть зроблені необов’язковими. Якщо у вас більше, ви можете використовувати оператор об’єднання:
type TypeWithOptionalProps = Optional
Заключні слова
Тепер ви можете зберегти цей загальний тип утиліти у файлі та експортувати його, щоб використовувати в усій програмі. Ось посилання на ігровий майданчик TypeScript, де я додав код із цієї статті та прокоментував його, щоб ви могли бачити, що відбувається, дивлячись на Partial
, Omit
, і наш загальний тип утиліти.
Світ генериків і утиліт є фантастичним у TypeScript. Займайтеся цим і починайте експериментувати!