TypeScript: возвращаемый тип при доступе к неопределенному ключу объекта неверен? - PullRequest
0 голосов
/ 29 апреля 2020

Я заметил неожиданные типы при использовании объектов с переменными ключами в TypeScript.

Учитывая следующий код

type MyType = {
  [x: number] : number
}

const o : MyType = {
  0: 1,
}

const a = o[0]; // Return type correctly identified as number
const b = o[1]; // Return type should be undefined and compiler should not allow this

Я заметил, что тип доступа к объекту с использованием [...] не правильно определяется, когда тип объекта определен с использованием синтаксиса [x: number] для переменных ключей.

VSCode показывает, что оба типа a и b имеют тип number. Вместо этого тип должен быть number | undefined, потому что может случиться так, что ключ не определен? При регистрации a и b на консоли a представляет собой number, а b - undefined.

Проблема становится более серьезной, когда объект типа MyType передается функции, и эта функция обращается к ключу в этом объекте, а затем делает что-то вроде этого:

function fun(o: MyType) : number {
   return o[10000] ?? null  // can be number or null at runtime
}

Ошибка не отображается. Но когда код выполняется, o[10000] не определено, и поэтому возвращаемое значение равно null, что не является допустимым числом. Представьте себе использование этого возвращаемого значения для выполнения дальнейших вычислений, которые все основаны на предположении, что это допустимое число. Это может привести к ошибкам во время выполнения, которые должны были быть обнаружены компилятором (если я не совсем понимаю, что-то не так, я новичок в TS)

(TypeScript, используемый в этих примерах, настраивается командой create-реагировать приложение, я не менял никаких настроек)

Ответы [ 2 ]

1 голос
/ 29 апреля 2020

Разве тип не должен быть числом | вместо этого вместо undefined, потому что может случиться так, что ключ не определен?

У вас есть такая опция, если хотите; просто определите его как:

type MyType = {
  [x: number] : number | undefined
}

Это может быть полезно, если вы ожидаете получить доступ к случайным свойствам, которые могут не существовать.

Однако, с другой стороны, довольно часто используются объекты более дисциплинированным образом, что исключает возможность доступа к несуществующим свойствам. Например, если вы обычно пишете код, который использует Object.keys(o) или for ... in, чтобы решить, к каким свойствам обращаться, то вы уже выполняете работу, чтобы убедиться, что он существует, и может быть неприятно, когда машинопись всегда говорит вам это может быть неопределенным.

0 голосов
/ 29 апреля 2020

Ваш MyType определяет индексный метод доступа, который позволяет использовать любое число в качестве метода доступа к объекту:

type MyType = {
  [x: number] : number
}

Это означает, что для обеспечения безопасности типов любое число может использоваться для получить доступ к объекту с помощью средства доступа к индексу, аналогично массиву.

Ваш объект определяет только одно свойство - но средство проверки типов (время компиляции) не смотрит на ваш объект, который создается во время выполнения. Все, что знает средство проверки типов, это MyType, и любое число является допустимым значением, которое можно использовать для индексации любого объекта, тип которого является или расширяется MyType.

Вы должны помнить, что ваш объект во время выполнения, все еще является обычным старым JavaScript объектом, и после того, как код скомпилирован и запущен, ничего не применяется к TypeScript.

Если вы хотите определить тип с заданным количеством свойств, то вам следует создать ваш тип с заданным числом свойств вместо использования средства доступа к индексу:

interface MyType {
  0: number
}

const o: MyType = { 0: 1 } // valid
const o2: MyType = { 1: 1 } // type checking error
o[0] // valid
o[1] // type checking error 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...