Exclude, Extract, NonNullable, ReturnType, InstanceType, Omit¶
Щоб заощадити час розробників, у систему типів TypeScript були включені кілька умовних типів, що часто потрібні, кожен з яких буде докладно розглянутий у цьому розділі.
Exclude (виключає T ознаки властиві U)¶
У результаті дозволу умовний тип Exclude представлятиме різницю типу T щодо типу U. Параметри типу T і U можуть бути як одиничним типом, так і безліччю union .
Простими словами, типу T будуть виключені ознаки (ключі), властиві також і типу U .
У випадку, якщо обидва аргументи типу належать до одного типу даних, Exclude буде представлений типом never .
Його реальну користь найкраще продемонструвати на реалізації функції, яка на вході отримує два різні об'єкти, а на виході повертає новий об'єкт, що складається з членів, присутніх у першому об'єкті, але відсутніх у другому. Аналог функції difference із широко відомої бібліотеки lodash.
Property 'a' is missing in type 'Pick' but required в type 'IA'. Type 'Pick' is missing the following properties from type 'IB': a, c
Extract (загальні для двох типів ознаки)
В результаті дозволу умовний тип Extract представлятиме перетин типу T щодо типу U . Обидва параметри типу можуть бути як звичайним типом, і union .
Простими словами, після дозволу Extract буде належати до типу, що визначається ознаками (ключами), властивими обох типів. Тобто тип Extract є протилежністю типу Exclude.
У випадку, коли загальних ознак немає, тип Extract буде представляти тип never .
Умовний тип Extract варто розглянути на прикладі реалізації функції, що приймає два об'єкти та повертає новий об'єкт, що складається з членів першого об'єкта, які також є і в другому об'єкті.
Property 'b' is missing in type 'Pick' but required в type 'IA'. Property 'c' is missing in type 'Pick' but required in type 'IB'.
NonNullable (видаляє типи null і undefined)¶
Умовний тип NonNullable служить виключення з типу ознак типів null і undefined . Єдиний параметр типу може належати як до звичайного типу, так і до безлічі визначається тип union .
Простими словами, цей тип видаляє з інструкції типу такі типи, як null і undefined .
У випадку, коли тип, що виступає в ролі єдиного аргументу типу, належить лише до типів null і\або undefined, NonNullable представляє тип never.
ReturnType (отримати тип значення, що повертається функцією)¶
Умовний тип ReturnType служить для встановлення типу, що повертається з функції. Як параметр типу повинен обов'язково виступати функціональний тип.
Насправді дуже часто потрібно отримати тип, якого належить значення, повертається з функції. Єдине, на що варто звернути увагу, що у випадках, коли тип значення, що повертається з функції, є параметром типу, у якого відсутні хоч якісь ознаки, то тип ReturnType буде представлений порожнім об'єктним типом <> .
InstanceType (отримати через тип класу тип його екземпляра)¶
Умовний тип InstanceType призначений для отримання типу екземпляра на основі типу класу. Параметр типу T повинен обов'язково належати до типу класу.
У більшості випадків ідентифікатор класу задіяний у додатку як тип його екземпляра.
Але складні програми часто вимагають динамічного створення своїх компонентів. У разі фабричні функції працюють над екземплярами класів, а безпосередньо з самими класами.
У JavaScript класи це лише синтаксичний цукор над старою доброю функцією конструктором. І, як відомо, об'єкт функції конструктора представляє об'єкт класу, що містить посилання на прототип, який представляє екземпляр. Іншими словами, в TypeScript ідентифікатор класу, зазначений в інструкції типу, представляє опис прототипу. Щоб отримати тип класу, необхідно виконати над ідентифікатором класу запит типу.
() => void
Property 'move' не існує на типі 'typeof Animal'.
Таким чином, грамотно обчислити тип екземпляра у фабричній функції можна за допомогою типу InstanceType.
Хоча можна вдатися і до менш декларативного способу - до запиту типу якості класу prototype.
І останнє, про що варто згадати, що результат отримання типу безпосередньо через any і never буде представлений ними. Інші випадки призведуть до виникнення помилки.
Parameters (отримати тип розміченого кортежу, який описує параметри функціонального типу)¶
Розширений тип Parameters призначений для отримання типів, вказаних в інструкції параметрів функції. Як аргумент типу очікується функціональний тип, на основі якого буде отримано розмічений кортеж, який описує параметри цього функціонального типу.
Parameters повертає типи параметрів як кортежу.
ConstructorParameters (отримати через тип класу розмічений кортеж, що описує параметри його конструктора)¶
Розширений тип ConstructorParameters призначений для отримання типів, вказаних в інструкції параметрів конструктора.
Як єдиний параметр типу ConstructorParameters очікує тип самого класу, на основі конструктора якого буде отримано розмічений кортеж, що описує параметри цього конструктора.
Omit (виключити з T ознаки, асоційовані з ключами, переліченими безліччю K)¶
Розширений тип Omit призначений визначення нового типу шляхом виключення заданих ознак з існуючого типу.
Як перший аргумент типу тип Omit очікує тип даних, з якого будуть виключені ознаки, пов'язані з ключами, переданими як другий аргумент типу.
Простими словами, до допомоги Omit слід вдаватися у разі необхідності визначення типу, що становить деяку частину вже існуючого типу.
Що таке OMIT у TS?
Основні типи TypeScript
- TypeScript - Типи
- TypeScript - Анотації типів
- TypeScript - Типизація за замовчуванням
- TypeScript - Числа
- TypeScript - Рядки
- TypeScript - Boolean
- TypeScript - Масиви
- TypeScript - Кортежі
- TypeScript - Перерахування
- TypeScript - Будь-який
- TypeScript - Ніколи
- TypeScript - Об'єднання
- TypeScript - Літеральні типи
- TypeScript - Символи
- TypeScript – null vs. undefined
- TypeScript - Типові Aliases
Потік керування TypeScript
- TypeScript - Прийняття рішень
- TypeScript - Умовна пропозиція
- TypeScript - Умова If Else
- TypeScript - Вкладені якщо
- TypeScript - Оператор switch
- TypeScript - Цикли
- TypeScript - Цикл For
- TypeScript - Цикл While
- TypeScript - Цикл Do While
- TypeScript - Функції
- TypeScript - Типи функцій
- TypeScript - Додаткові параметри
- TypeScript -.dfault Parameters
- TypeScript - Анонімні функції
- TypeScript - Конструктор функції
- TypeScript - Загальний параметр
- TypeScript - Розбір параметрів
- TypeScript - Стрілочні функції
Класи та Об'єкти TypeScript
- TypeScript - Класи
- TypeScript - Об'єкти
- TypeScript - Модифікатори доступу
- TypeScript - Псевдографічні властивості
- TypeScript - Спадкування
- TypeScript - Статичні методи та властивості
- TypeScript - Абстрактні класи
- TypeScript - Акцесори
- TypeScript - Качиний тип
Просунуті типи TypeScript
Маніпуляція типами TypeScript
Різне для TypeScript
- TypeScript - Потрійні косі лінії директив
- TypeScript - Простір імен
- TypeScript - Модулі
- TypeScript - Ambients
- TypeScript - Декоратори
- TypeScript - Сумісність типів
- TypeScript - Об'єкт дати
- TypeScript - Ітератори та генератори
- TypeScript - Міксини
- TypeScript - Утилітарні типи
- TypeScript - Boxing та Unboxing
- TypeScript - tsconfig.json
- Від JavaScript до TypeScript
- TypeScript - Головна
- TypeScript - Огляд
- TypeScript - Налаштування оточення
- TypeScript - Основна Синтаксис
- TypeScript проти JavaScript
- TypeScript - Особливості
- TypeScript - Змінні
- TypeScript - let та const
- TypeScript - Оператори
Основні типи TypeScript
- TypeScript - Типи
- TypeScript - Анотації типів
- TypeScript - Типизація за замовчуванням
- TypeScript - Числа
- TypeScript - Рядки
- TypeScript - Boolean
- TypeScript - Масиви
- TypeScript - Кортежі
- TypeScript - Перерахування
- TypeScript - Будь-який
- TypeScript - Ніколи
- TypeScript - Об'єднання
- TypeScript - Літеральні типи
- TypeScript - Символи
- TypeScript – null vs. undefined
- TypeScript - Типові Aliases
Потік керування TypeScript
- TypeScript - Прийняття рішень
- TypeScript - Умовна пропозиція
- TypeScript - Умова If Else
- TypeScript - Вкладені якщо
- TypeScript - Оператор switch
- TypeScript - Цикли
- TypeScript - Цикл For
- TypeScript - Цикл While
- TypeScript - Цикл Do While
- TypeScript - Функції
- TypeScript - Типи функцій
- TypeScript - Додаткові параметри
- TypeScript -.dfault Parameters
- TypeScript - Анонімні функції
- TypeScript - Конструктор функції
- TypeScript - Загальний параметр
- TypeScript - Розбір параметрів
- TypeScript - Стрілочні функції
Класи та Об'єкти TypeScript
- TypeScript - Класи
- TypeScript - Об'єкти
- TypeScript - Модифікатори доступу
- TypeScript - Псевдографічні властивості
- TypeScript - Спадкування
- TypeScript - Статичні методи та властивості
- TypeScript - Абстрактні класи
- TypeScript - Акцесори
- TypeScript - Качиний тип
Просунуті типи TypeScript
Маніпуляція типами TypeScript
Різне для TypeScript
- TypeScript - Потрійні косі лінії директив
- TypeScript - Простір імен
- TypeScript - Модулі
- TypeScript - Ambients
- TypeScript - Декоратори
- TypeScript - Сумісність типів
- TypeScript - Об'єкт дати
- TypeScript - Ітератори та генератори
- TypeScript - Міксини
- TypeScript - Утилітарні типи
- TypeScript - Boxing та Unboxing
- TypeScript - tsconfig.json
- Від JavaScript до TypeScript
TypeScript - Утилітарні типи
Здрастуйте, майбутні кодингові маги! Сьогодні ми вирушимо в захоплюючу подорож магічним світом утилітарних типів TypeScript. Не хвилюйтеся, якщо ви новачки у програмуванні; я буду вашим дружнім провідником, і ми разом досліджуємо ці концепції крок за кроком. Так що візьміть свої віртуальні палички (клавіатури) і lets dive in!
Що таке утилітарні типи?
Перш ніж ми почнемо, зрозуміємо, що таке утилітарні типи. Уявіть собі ящик із різними інструментами. Кожен інструмент допомагає вам виконувати певне завдання ефективніше. Саме такими і є утилітарні типи в TypeScript - це інструменти, які допомагають нам маніпулювати і перетворювати типи легко.
Тепер давайте розглянемо кожен із цих магічних інструментів по одному!
Тип Partial у TypeScript
Тип Partial resembles a spell що робить всі властивості в object optional. Це super useful when you want to create object where you don't need to specify all properties.
Давайте побачимо це у дії:
interface Wizard < name: string; age: number; house: string; >function updateWizard(wizard: Wizard, fieldsToUpdate: Partial) < return < . wizard, . fieldsToUpdate >; > const harryPotter: Wizard = < name: "Harry Potter", age: 11, house: "Gryffindor" >; const updatedHarry = updateWizard(harryPotter, < age: 17 >); console.log(updatedHarry); // Висновок:
У цьому прикладі Partial дозволяє нам оновити лише вік Гарі, не вказуючи решту властивостей. Це як змахнути паличкою та сказати "Partial Revelio!"
Тип Required в TypeScript
Тип Required - це рівність Partial. Це як casting a spell що робить всі властивості в об'єкті обов'язковими, навіть якщо вониoriginally були可选.
interface MagicalCreature < name: string; power?: string; age?: number; >const dragon: Required = < name: "Norwegian Ridgeback", Power: "Fire Breath", age: 2 >; // Це викликало б помилку: // const unicorn: Required = < // name: "Silver Horn" //>;
Тут, навіть though power і age були可 у вихідному інтерфейсі, тип Required робить їх обов'язковими. Це як сказати "Accio all properties!"
Тип Pick у TypeScript
Тип Pick дозволяє створити новий тип, вибравши конкретні властивості з існуючого типу. Це як використовувати заклинання Summoning Charm, щоб покликати лише ті властивості, які вам потрібні.
interface Potion < name: string; ingredients: string[]; brewingTime: number; effect: string; >type PotionLabel = Pick; const polyjuicePotion: PotionLabel = < name: "Polyjuice Potion", ефект: "Transforms drinker in another person" >;
У цьому прикладі ми створили новий тип PotionLabel, який включає лише властивості name та effect з інтерфейсу Potion. Це ідеально для тих випадків, коли вам потрібно лише кілька конкретних деталей!
Тип Omit у TypeScript
Тип Omit - це основа Pick. Він створює новий тип, видаляючи конкретні властивості існуючого типу. Уявіть, що ви використовуєте заклинання Vanishing Spell на деяких властивостях!
interface SpellBook < title: string; author: string; pages: number; secretSpell: string; >type PublicSpellBook = Omit; const beginnerSpellBook: PublicSpellBook = < title: "Standard Book of Spells, Grade 1", автор: "Miranda Goshawk", pages: 250 >;
Тут ми створили тип PublicSpellBook, який включає всі властивості SpellBook, крім secretSpell. Це як сказати "Show me everything but the secret!"
Тип Readonly у TypeScript
Тип Readonly resembles a protection spell on your properties. Це дає всі види в типі read-only, роблячи accidental modifications.
interface Wand <wood: string; core: string; length: number; >const harryWand: Readonly = <wood: "Holly", core: "Phoenix feather", length: 11 >; // Це викликало б помилку: // harryWand.length = 12;
За допомогою Readonly ми вважаємо, що після створення палички її властивості не можна змінити. Це як накласти заклинання на ваші об'єкти!
Тип ReturnType у TypeScript
Тип ReturnType дозволяє вибрати тип значення значення функції. Це як використовувати заклинання Legilimency, щоб заглянути у функцію та побачити, що вона повертає!
function castSpell(spellName: string): < name: string, power: number >< // Логіка cast заклинання тут return < name: spellName, power: Math.random() * 100 >; > type SpellResult = ReturnType; const lumos: SpellResult = < name: "Lumos", Power: 50 >;
У цьому прикладі SpellResult виводиться як < name: string, power: number >, що є типом значення значення функції castSpell . Це надзвичайно корисно при роботі зі складними функціями!
Тип Record у TypeScript
Тип Record - це powerful заклинання, яке створює об'єктний тип із конкретним типом ключа та типом значення. Це як закликати магічну карту, де ви визначаєте, якими мають бути ключі та значення.
type HouseCup = Record; const housePoints: HouseCup = < "Gryffindor": 472, "Hufflepuff": 352, "Ravenclaw": 426, "Slytherin": 472 >;
Тут HouseCup – це тип, де ключі – це рядки (імена будинків), а значення – це числа (окуляри). Це гарантує, що наш об'єкт окулярів має правильну структуру.
Тип NonNullable у TypeScript
Тип NonNullable resembles a spell to banish null and undefined values. Це створює новий тип за винятком null і undefined from a given type.
Тип MagicalItem = string | number | null | undefined; type DefiniteMagicalItem = NonNullable; const definiteItem: DefiniteMagicalItem = "Invisibility Cloak"; // Це викликало б помилку: // const nullItem: DefiniteMagicalItem = null;
У цьому прикладі DefiniteMagicalItem - це тип, який може бути рядком або числом, але не null або undefined. Це ідеально, коли ви хочете бути впевнені, що працюєте з actual значеннями!
Шпаргалка за утилітарними типами
Ось quick reference таблиця для всіх типів утилітарних, які ми розглянули:
| Утилітарний тип | Опис | приклад |
|---|---|---|
| Partial | Makes all properties in T optional | Partial |
| Required | Makes all properties in T required | Required |
| Pick | Creates a type with only the properties K від T | Pick |
| Omit | Creates a type without the properties K від T | Omit |
| Readonly | Makes all properties in T read-only | Readonly |
| ReturnType | Extracts the return type of function type T | ReturnType |
| Record | Створюйте object type with keys of type K and values of type T | Record |
| NonNullable | Creates a type by excluding null and undefined from T | NonNullable |
І ось ви,年轻的巫师们! Тепер ви освоїли базові заклинання утилітарних типів TypeScript. Пам'ятайте, як будь-яка магія, ці типи стають більш powerful з практикою. Так що продовжуйте експериментувати, і незабаром ви будете cast цих типів так само легко, як saying "Wingardium Leviosa"!
Credits: Image by storyset
The Omit Helper Type в TypeScript
In version 3.5, TypeScript added an Omit helper type to the lib.es5.d.ts type definition file that ships as part of the TypeScript compiler. The Omit type lets us create object type that omits specific properties from another object type:
type
User
=
id:
string;
name:
string;
email:
string;
>;
type
UserWithoutEmail
=
OmitUser,
"email">;
// This is equivalent to:
type
UserWithoutEmail
=
id:
string;
name:
string;
>;
The Omit helper type is defined in lib.es5.d.ts like this:
/**
* Конструювати тип з ознаками T except for those in typ K.
*/
type
OmitT,
K
extends
keyof
any>
=
PickT,
Excludekeyof
T,
K>>;
Для того, щоб цей тип definition and understand how it works, let's see how we could've come up with our own version of Omit helper typ ourselves.
Defining the Omit Helper Type #
Let's start with the same User type we've seen above:
type
User
=
id:
string;
name:
string;
email:
string;
>;
Перший, щоб бути використаним, щоб скористатися всіма кнопками з User type. Ви можете використовувати keyof operator, щоб від'єднати union string literal types, що знаходять all property keys of this object type:
type
UserKeys
=
keyof
User;
// This is equivalent to:
type
UserKeys
=
"id"
|
"name"
|
"email";
Далі, ми повинні бути здатні до вилучення конкретних string literal type from union of string literal types. У випадку з нашим User type, ми повинні виключити тип "email" від union "id" | "name" | "email" . We can use the Exclude helper type to do that:
type
UserKeysWithoutEmail
=
ExcludeUserKeys,
"email">;
// This is equivalent to:
type
UserKeysWithoutEmail
=
Exclude"id"
|
"name"
|
"email",
"email">;
// This is equivalent to:
type
UserKeysWithoutEmail
=
"id"
|
"name";
The Exclude type is defined in lib.es5.d.ts like this:
/**
* Exclude from T those types that are assignable to U
*/
type
ExcludeT,
U>
=
T
extends
U
?
never
:
T;
Це використовує кондиційний тип і невідомий тип. За допомогою виключного helper type, ми скористаємося цими типами в нашому вигляді типу "id" | "name" | "email" that є assignable до "email" type. Це є тільки true для string literal type "email" itself, so we're left with union type "id | "name" .
Власне, ми потрібні для створення об'єкта типу, що містить позначки з властивостей нашого типу. Відомо, ми збираємося створити об'єкт типу, що містить тільки ті властивості, які ключі знаходяться в UserKeysWithoutEmail union type. We can use the Pick helper type to pick those properties off of our User type:
type
UserWithoutEmail
=
PickUser,
UserKeysWithoutEmail>;
// This is equivalent to:
type
UserWithoutEmail
=
PickUser,
"id"
|
"name">;
// This is equivalent to:
type
UserWithoutEmail
=
id:
string;
name:
string;
>;
Тут's how the Pick helper type is defined within lib.es5.d.ts:
/**
* З T, натисніть на set properties whose keys are in the union K
*/
type
PickT,
K
extends
keyof
T>
=
[P
in
K]:
T[P];
>;
Pick type is mapped type that's using the keyof operator and indexed access type T[P] to retrieve the type of the property P in the object type T .
Now, let's summarize all the typ operations we've performed using keyof , Exclude , and Pick in a single type:
type
UserWithoutEmail
=
PickUser,
Excludekeyof
User,
"email">>;
Notice that this type is specific to our User type. Let's make this a generic type so we can reuse it in other places:
type
OmitT,
K>
=
PickT,
Excludekeyof
T,
K>>;
Ви можете скористатися цим типом для compute нашого UserWithoutEmail type:
type
UserWithoutEmail
=
OmitUser,
"email">;
Відмінні об'єкти клавіші можуть бути тільки strings, numbers, або symbols, we can add generic constraint to the type parameter
type
OmitT,
K
extends
string
|
number
|
symbol>
=
PickT,
Excludekeyof
T,
K>>;
Найголовніші загрожують довжинами string | number | symbol is a bit verbose. We can replace the string | number | символ union type by keyof any type since the two are equivalent:
type
OmitT,
K
extends
keyof
any>
=
PickT,
Excludekeyof
T,
K>>;
And there we go! We've arrived at the exact definition of the Omit helper type as it is found within the lib.es5.d.ts type definition file:
/**
* Конструювати тип з ознаками T except for those in typ K.
*/
type
OmitT,
K
extends
keyof
any>
=
PickT,
Excludekeyof
T,
K>>;
Unrolling Omit #
Тут ви можете сконтактувати зразок Omit типу. Try to follow every step to understand how TypeScript is computing the final type:
type
User
=
id:
string;
name:
string;
email:
string;
>;
type
UserWithoutEmail
=
OmitUser,
"email">;
// This is equivalent to:
type
UserWithoutEmail
=
PickUser,
Excludekeyof
User,
"email">>;
// This is equivalent to:
type
UserWithoutEmail
=
PickUser,
Exclude"id"
|
"name"
|
"email",
"email">>;
// This is equivalent to:
type
UserWithoutEmail
=
Pick
User,
|
("id"
extends
"email"
?
never
:
"id")
|
("name"
extends
"email"
?
never
:
"name")
|
("email"
extends
"email"
?
never
:
"email")
>;
// This is equivalent to:
type
UserWithoutEmail
=
PickUser,
"id"
|
"name"
|
never>;
// This is equivalent to:
type
UserWithoutEmail
=
PickUser,
"id"
|
"name">;
// This is equivalent to:
type
UserWithoutEmail
=
[P
in
"id"
|
"name"]:
User[P];
>;
// This is equivalent to:
type
UserWithoutEmail
=
id:
User["id"];
name:
User["name"];
>;
// This is equivalent to:
type
UserWithoutEmail
=
id:
string;
name:
string;
>;
Et voilà, our final UserWithoutEmail type.
Цей матеріал і 44 інших є частиною TypeScript Evolution series. Have a look!
Advanced TypeScript Fundamentals
A deep dive into fundamnetals of TypeScript's type system. Дослідження про опційні chaining (?.) і nullish coalescing ( ?? ) Operators, asertion functions, truly private class fields, conditional types, template literal types, adn more.
