Ответ вслух Senior Условные и mapped-типы обновлено

Распределение условных типов

Вопрос

Объясните, как условный тип ведёт себя с объединением и когда это мешает.

Попробуйте сами

Ответьте вслух за 2 минуты, как на собесе. Потом сверьтесь с тезисами: что прозвучало, а что нет.

Показать ответ и разбор

Коротко

Если в условном типе слева от extends стоит голый параметр T, а при использовании в него подставили объединение, TypeScript применяет условие к каждому члену отдельно и объединяет результаты. Поэтому Exclude<'a' 'b', 'a' это 'b': для 'a' условие даёт never, для 'b' сам 'b'.

Что должно прозвучать в ответе

  • Голый параметр в `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 ошибок.