TypeScript со строгой проверкой нуля - как насчет доступа к массиву?

В TypeScript, если включена строгая проверка нуля, я ожидаю, что компилятор не позволит мне назначить null или же undefined значения переменной, если она не допускает null,

Однако доступ к массиву позволяет обойти эту проверку.

Пример:

let a: string[] = ["Hello"];
let s: string;

// 1) this produces an error, as expected
s = undefined

// 2) s is undefined here, too, but no error
s = a[3];
console.log(s);

Запускаемая версия на TypeScript Playground (примечание: в диалоговом окне "Параметры" должна быть включена "строгая проверка нуля").

Что здесь происходит?

  • Это ошибка в компиляторе TypeScript?
  • Или это намеренное упущение?
  • Если последнее, документировано ли это где-нибудь (в идеале с обоснованием, почему это было сделано)?

2 ответа

Решение

Нашел это:-).

tl; dr: это намеренное упущение. Доступ к массиву очень распространен в коде TypeScript, и принудительная проверка нулевого / неопределенного для каждого доступа считалась слишком громоздкой для разработчиков.


Эта проблема поднималась несколько раз в дискуссиях:

Комментарий к PR 7140 имеет хорошее обоснование от Андерса Хейлсберга (одного из разработчиков ядра):

Индексирование просто создает значение типа, объявленного в соответствующей сигнатуре индекса. Даже если это технически более правильно, было бы слишком больно, если бы мы автоматически добавили undefined к типу каждой операции индексации.

Например, каждый доступ к элементу массива должен сопровождаться ненулевой защитой или ! утверждение. Я думаю, это стало бы очень раздражающим.

TypeScript 4.1 представил новую опцию компилятора — noUncheckedIndexedAccess. Среди прочего добавляется undefinedк типу доступа к индексу массива.

Рассмотрим следующий фрагмент (игровая площадка TS ):

      const items = [1,2,3]
console.log(items[1]?.toString(10))
console.log(items[2].toString(10))

Без noUncheckedIndexedAccess, items[2].toString(10)будет считаться действительным и недействительным, если опция включена. items[1]?.toString(10)будет действителен, когда эта опция включена, как в комментарии Алекса Нета в старом ответе.

Другие вопросы по тегам