Объявлен тип с Typescript, но Javascript внутренне работает с неправильным типом - PullRequest
0 голосов
/ 05 февраля 2020

Я довольно новичок в Typescript и работаю над учебным видео. Вчера я обнаружил странное поведение и считаю, что это ошибка. Пример:

const json = '{"x": 10, "y":10}';
const coordinates: { x: number; y: number } = JSON.parse(json);

console.log(typeof coordinates.y);

Обычно выводит x и y как номер типа. Но это не из-за объявления типа, это из-за значения JSON. Если вы объявляете один из них как String, VS Code обрабатывает его как String, но внутренне он остается числом:

const json = '{"x": 10, "y":10}';
const coordinates: { x: number; y: string } = JSON.parse(json);

console.log(typeof coordinates.y);

Это код:

The y variable is typed as a string

Как видите, VS Code обрабатывает его как строку

The output of this is type number

Но проверка типа доказывает, что это не правильно.

На мой взгляд, имеет смысл, что объект / массив после разбора имеет любой тип. но это должно быть либо сообщение об ошибке, если проанализированное JSON -значение отличается от вашей аннотации, либо оно должно преобразовать заданное значение точно в аннотацию.

Я совершенно новичок в этом, так что если мое предположение неверно, пожалуйста, дайте мне знать!

1 Ответ

2 голосов
/ 05 февраля 2020

Typescript делает вывод до и во время компиляции . После компиляции в JS, если некоторые из типов кода вашего кода c не работают, некоторые из объявленных вами типов могут быть недействительными. Это то, что здесь происходит.

JSON.parse возвращает что-то типа any, которое может быть буквально любым . Вы можете попытаться извлечь из него свойства с помощью строки:

const coordinates: { x: number; y: string } = JSON.parse(json);

Но это не означает, что анализируемый объект будет фактически иметь свойство x как число или свойство y как string - ваш код говорит компилятору предположить , что он делает, и обрабатывать y как строку позже в коде.

Если у вас есть что-то, по умолчанию , типа any, при извлечении свойств из него вы должны убедиться, что его свойства действительно соответствуют тому типу, который вы для них обозначаете. Если вы не уверены на 100%, что свойства всегда будут такими, как ожидалось (например, если входная строка поступает из сетевого ответа - что если ответ 503?), Сделайте защиту типа, например:

const isCoordinates = (param: unknown): param is { x: number, y: number } => {
    return typeof param === 'object' && param !== null && 'x' in param;
};

Затем вызовите isCoordinates, прежде чем пытаться извлечь свойства из строки, чтобы убедиться, что она соответствует ожидаемому вами формату.

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

Вы можете включить правило tslint no-unsafe-any , чтобы избежать ошибок такого рода. .

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