Awaited
Проблема
У TypeScript есть типы, которые оборачивают другие типы, например Promise<T>
.
Как мы достанем внутренний тип из такого типа? Например, если у нас есть
Promise<ExampleType>
, то как мы достанем из него ExampleType
?
Решение
Интересная проблема, для решения которой нужно знать об одной из возможностей системы типов у TypeScript, которую редко используют, и зря!
Но прежде чем перейдём к объяснению, давайте проанализируем проблему. Автор просит распаковать тип. Что значит “распаковать тип”? Распаковка типа это процесс извлечения внутреннего типа из окружающего его.
Давайте с примером. Если у вас есть тип Promise<string>
, то распаковка такого
типа Promise
приведёт к типу 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
. R
станет доступным в нашей правдивой
ветке условного типа, откуда мы его и возвращаем.
type Awaited<T> = T extends Promise<infer R> ? R : T;
Комментарии