Распределение условных типов
Вопрос
Объясните, как условный тип ведёт себя с объединением и когда это мешает.
Попробуйте сами
Ответьте вслух за 2 минуты, как на собесе. Потом сверьтесь с тезисами: что прозвучало, а что нет.
Показать ответ и разбор
Коротко
Что должно прозвучать в ответе
Голый параметр в `T extends U` даёт распределение по членам объединения
На этом построены `Exclude`, `Extract`, `NonNullable`
`never` как пустое объединение даёт `never` в результате
Отключение: `[T] extends [U]`, нужно для `IsNever` и проверок всего объединения
Распределение срабатывает только для параметра типа, а не для конкретного объединения, записанного прямо в условии
Что могут спросить следом
- Почему
Excludeработает поэлементно? - Как проверить, что тип является объединением?
- Что вернёт
boolean extends true ? 1 : 2?
Разбор
Если в условном типе слева от extends стоит голый параметр T, а при использовании в него подставили объединение, TypeScript применяет условие к каждому члену отдельно и объединяет результаты. Поэтому Exclude<'a' | 'b', 'a'> это 'b': для 'a' условие даёт never, для 'b' сам 'b'. Следствие, о котором забывают: never это пустое объединение, и результат для него never, ветки не вычисляются. Мешает распределение, когда нужно проверить тип целиком: IsNever, IsUnion, или когда boolean неожиданно распадается на true | false. Тогда оборачиваю обе стороны в кортеж: [T] extends [never]. И важно: распределение работает только через параметр типа. В выражении boolean extends true ? 1 : 2 параметра нет, и ответ просто 2.
Ответьте сами, а не прочитайте
В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.