#javascript #typescript #object #compiler-errors #typescript-typings
#javascript #typescript #объект #ошибки компилятора #typescript-типизации
Вопрос:
Я обнаружил некоторое странное поведение в коде Typescript, который я пишу.
Ссылка на игровую площадку Typescript
Каким-то образом Typescript не вызывает ошибку для неинициализированного свойства, если имя этого свойства name
:
Что это? Это ошибка или что?
Это ошибка для value
свойства:
В области видимости для сокращенного свойства «value» не существует значения. Либо объявите его, либо укажите инициализатор.(18004)
interface INTERFACE_A {
name: string, // ALSO TRIED WITH OTHER TYPES. SAME RESULT
}
function fooA(x: INTERFACE_A): INTERFACE_A { return x; }
fooA({
name // THIS SHOULD BE AN ERROR (BUT IT'S NOT)
});
const objA: INTERFACE_A = {
name // THIS SHOULD BE AN ERROR (BUT IT'S NOT)
}
interface INTERFACE_B {
value: string
}
function fooB(x: INTERFACE_B): INTERFACE_B { return x; }
fooB({
value // THIS IS AN ERROR (OK)
});
const objB: INTERFACE_B = {
value // THIS IS AN ERROR (OK)
}
Похоже, это не связано с игровой площадкой Typescript, поскольку это также происходит в моей среде разработки VSCode:
Обновить:
Вероятно, это связано со window.name
свойством, которое имеет тип string
. Но он по-прежнему ведет себя иначе, чем window.innerWidth
, например:
Посмотрите, что TS жалуется, если я использую innerWidth
как a string
, но он не жалуется, когда я пытаюсь использовать window.name
как number
:
Комментарии:
1. @arslan2012 Я добавил игровую площадку просто в качестве примера. Но это также происходит в моей локальной среде разработки на VSCode. Я не думаю, что это связано с игровой площадкой.
Ответ №1:
{ name }
является сокращением для { name: name }
, window.name
является встроенным свойством, а свойства window
являются глобальными в браузерах, поэтому name
глобальное свойство эквивалентно window.name
.
По сути, ваш код делает это:
fooA({
name: window.name
})
и это абсолютно справедливо (хотя, вероятно, не то, что вы хотели).
Комментарии:
1. Я думаю, что вы частично правы. Потому что, если я изменяю
name: string
наinnerWidth: string
, я получаю сообщение об ошибке, в котором говорится, чтоstring is not assignable to number
, посколькуwindow.innerWidth
это число. Но если я перейду наname: number
TS, он по-прежнему молчит и не жалуется, чтоwindow.name
должно бытьstring
. Я имею в виду, что там есть что-то более странное, IMO. Посмотрите новые экраны, которые я добавил к вопросу.2. Как ни странно, кажется, что TypeScript вводит
name
asnever
, т. Е. Кажется, что он отличается отwindow.name
(что естьstring
). Ссылка на игровую площадку Это объясняет отсутствие ошибки, посколькуnever
присваивается чему угодно.3. @Cerberus Спасибо. Тогда, вероятно, это так. Но когда я это делаю
const name = window.string
. Этаname
переменная оценивается какstring
.4. Да, это то, что я тоже сказал:
window.name
естьstring
, но простоname
(если это не определено вашим кодом, очевидно) естьnever
.
Ответ №2:
Для решения такого рода ошибок ESLint можно настроить на выдачу ошибок при использовании глобальных параметров браузера, например name
, без явной ссылки на объект window ( window.name
)
- Установите ESLint
- Установите ESLint и it для кода typescript (инструкции здесь)
- установите
no-restricted-globals
пакет - Добавьте это в свои правила в
.eslintrc.js
:
module.exports = {
// ... other fields omitted
rules: {
// ... other rules omitted
"no-restricted-globals": ["error"].concat(
require("confusing-browser-globals")
),
},
}