Typescript не вызывает ошибок для неинициализированного свойства объекта с именем «name»

#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 :

Ссылка на игровую площадку Typescript

введите описание изображения здесь

введите описание изображения здесь

Комментарии:

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 as never , т. Е. Кажется, что он отличается от window.name (что есть string ). Ссылка на игровую площадку Это объясняет отсутствие ошибки, поскольку never присваивается чему угодно.

3. @Cerberus Спасибо. Тогда, вероятно, это так. Но когда я это делаю const name = window.string . Эта name переменная оценивается как string .

4. Да, это то, что я тоже сказал: window.name есть string , но просто name (если это не определено вашим кодом, очевидно) есть never .

Ответ №2:

Для решения такого рода ошибок ESLint можно настроить на выдачу ошибок при использовании глобальных параметров браузера, например name , без явной ссылки на объект window ( window.name )

  1. Установите ESLint
  2. Установите ESLint и it для кода typescript (инструкции здесь)
  3. установите no-restricted-globals пакет
  4. Добавьте это в свои правила в .eslintrc.js :
 module.exports = {
  // ... other fields omitted
  rules: {
    // ... other rules omitted
    "no-restricted-globals": ["error"].concat(
      require("confusing-browser-globals")
    ),
  },
}