Выбор ответа Senior Объединения и сужение обновлено

Сужение внутри замыкания

Вопрос

Что скажет TypeScript 5.4+?

let v: string | number = Math.random() > 0.5 ? 'a' : 1;
if (typeof v === 'string') {
  const up = () => v.toUpperCase();
}
v = 1;

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

Выберите вариант, и откроется разбор.

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

Коротко

Правильный ответ: Ошибка в стрелке: у string number нет toUpperCase. Сужение let переносится внутрь замыкания, только если после создания замыкания переменной больше ничего не присваивают.

Варианты ответа

  1. Ошибка в строке v = 1: число нельзя присвоить
  2. Ошибка: let-переменную нельзя использовать в замыкании
  3. Всё компилируется: внутри стрелки v уже string
  4. Ошибка в стрелке: у string | number нет toUpperCaseправильный ответ

Разбор

Сужение let переносится внутрь замыкания, только если после создания замыкания переменной больше ничего не присваивают. Здесь ниже есть v = 1, функцию могут вызвать уже после него, поэтому внутри стрелки v снова string | number, и вызов toUpperCase не компилируется.

Без строки v = 1 в TypeScript 5.4+ всё бы скомпилировалось. Само присваивание числа корректно: тип переменной string | number. Использовать let в замыкании можно.

Ответьте сами, а не прочитайте

В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.