Awaited
Завдання
В TypeScript є типи, які обгортають інші типи, наприклад Promise
. Як ми можемо
дістати внутрішній тип з такої обгортки? Наприклад, як отримати ExampleType
з
Promise<ExampleType>
?
Розв’язок
Досить цікава проблема, для вирішення якої потрібно знати про одну з можливостей системи типів в TypeScript, яку досить рідко використовують.
Але перед тим, як пояснити, що я маю на увазі, проаналізуймо завдання. Автор просить нас розгорнути тип. Що означає “розгорнути тип”? Розгорнути тип - означає дістати внутрішній тип із зовнішнього.
Розгляньмо на прикладі. Якщо ми маємо тип Promise<string>
, то його розгортання
дасть нам тип string
, тому що він всередині Promise
.
Тож, до завдання. Розпочнімо з найпростішого прикладу. Якщо наш тип Awaited
отримує Promise<string>
, нам потрібно повернути string
. Інакше ми повернемо
сам T
, бо він не є Promise
, а отже повертаємо без змін. Для цього
використаємо умовні типи:
type Awaited<T> = T extends Promise<string> ? string : T;
Але в цьому рішенні є проблема. За цією логікою, ми можемо дістати тільки рядки
в Promise
, а нам потрібно підтримувати будь-який тип. Тож, як цього досягти?
Як дістати тип з Promise
, якщо ми не знаємо що там?
Для цього, в TypeScript є виведення типів в умовних типах! Ми можемо сказати компілятору: “як тільки ти знатимеш, що це за тип, присвой його, будь ласка, моєму тип параметрові”. Ви можете прочитати більше про це тут.
Знаючи про виведення, ми можемо покращити наше рішення. Замість перевірки на
Promise<string>
у нашому умовному типі, ми замінимо string
на infer R
. Бо
ми не знаємо, що там за тип (поки що). Єдине, що ми знаємо, це те, що це
Promise<T>
з якимось типом всередині.
Як тільки TypeScript зрозуміє, який тип знаходиться всередині Promise
, він
присвоїть його нашому параметрові R
і стане доступним у гілці “true” умовного
типу, звідки ми його і повернемо.
type Awaited<T> = T extends Promise<infer R> ? R : T;
Коментарі