Властивість 'записи' не існує у типі 'ObjectConstructor'


76

Я працюю над реалізацією ng2. Я використовую наступний виклик функції для перетворення об’єкта в масив:

var authors = Object.entries(responseObject.Authors);

Це стандартна функція js. Однак компілятор ts повертає таку помилку:

"Property 'entries' does not exist on type 'ObjectConstructor'"

На основі швидкого google виявляється, що рішенням може бути зміна цільової властивості compilerOptions з es5 на es6. Однак після деяких попередніх досліджень попереднього випуску я подумав, що зміг використати функціональність es6, включивши додаткове властивість "lib" на моєму tsconfig.json нижче:

  "compilerOptions": {
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "module": "commonjs",
    "noEmitOnError": true,
    "noImplicitAny": false,
    "outDir": "../Scripts/",
    "removeComments": false,
    "sourceMap": true,
    "target": "es5",
    "moduleResolution": "node",
    "lib": [
      "es2015",
      "dom"
    ]
  }

Я також спробував змінити цільову властивість на es2015, а потім відновив проект і виконав "typecriptUsingTsConfig", але все одно отримую ту ж помилку. Будь-яка ідея, що я можу зробити тут, щоб використати функцію Object.entries ()?

Відповіді:


126

Ви цілком праві, що зміна target- це неправильний підхід, а зміна lib- це правильний підхід, однак ви вказали неправильну версію мови. Згідно з MDN , Object.entriesбуло офіційно додано до специфікації ES2017.

"lib": ["es2017"]

тому ви повинні вказати замість цього *.

Якщо ви хочете додати лише декларації для методів Objectфункції, які були додані в ES2017, TypeScript дозволяє вказати більш детальне значення .

"lib": ["es2017.object"]

Як зазначав Олександр Берд, за замовчуванням неявне значення "lib"опції залежить від значення, вказаного для "target"наявності.

Наприклад:

"target": "es2017"

Приведе до того, що відповідний префікс "lib.*"буде включено за замовчуванням, якщо "lib"це не вказано явно.

Зауважте, що ви, швидше за все, захочете додати поліфіл самої реалізації, такий як цей , щоб переконатися, що це працює у старих версіях.

Примітка: як альтернативу ви можете вказати будь-яку пізнішу версію

"lib": ["es2020"]

або, природно, навіть

"lib": ["esnext"] 

Це останнє включатиме декларації про найновіші стандартні функції бібліотеки, відомі мові TypeScript. Оскільки він представляє рухому ціль, цим параметром слід користуватися з обережністю, оскільки полізаповнення всього відповідного середовища виконання за визначенням є складним завданням, яке потребує досліджень і може включати завантаження різних полізаповнювачів залежно від цільового часу роботи.

Крім того, характер масиву "lib"опції дозволяє поєднувати кілька значень відповідно до вашого часу роботи. Наприклад, щоб зіставити веб-браузери, що підтримують es2015, з додаванням цих об’єктних методів, передбачених polyfill, можна

"lib": ["es2015", "es2017.object", "dom"]

Додаткові відомості див. У довіднику TypeScript .

Примітка: кілька коментаторів запитали, чому було б неправильно змінювати --targetзамість того, --libяк обидва дозволяли коду вводити перевірку? Причина полягає в тому, що --targetзмінюється спосіб трансляції коду. Наприклад, "target": "es2017"означає, що asyncфункції не будуть трансформовані для старих середовищ виконання. Це неправильно, оскільки метою було дозволити використання додаткових бібліотек, а не змінювати вихідний синтаксис, і тому важливо розрізняти синтаксичні ознаки та особливості бібліотеки.


1
@ user8334943 ні, вам точно знадобиться поліфіл для IE 10. Посилання MDN містить інформацію про підтримку браузера внизу.
Aluan Haddad

1
Примітка для інших: якщо ви вже не використовували libопцію компілятора, можливо, за вашим цільовим значенням було значення за замовчуванням, яке буде замінено, коли ви встановите lib. Перегляньте документацію до параметрів компілятора для переліку за замовчуванням. Мені довелося явно додати libпараметри за замовчуванням для моєї цілі, а також es2017.object.
alexanderbird

1
@AluanHaddad точно :) Я погоджуюсь тримати оновлення якомога довше, і незабаром виконаю оновлення. Це великий додаток, у якого багато розробників, тому оновлення потрібно планувати. Дякуємо за ваш внесок!
Джессі

1
Чому правильніше оновлювати libзамість target?
rjh

1
@rjh Target змінює спосіб трансляції коду. Наприклад, "target": "es2017"означає, що asyncфункції не будуть трансформовані для старих середовищ виконання. Це неправильно, оскільки метою було дозволити використання додаткових бібліотек, а не змінити вихідний синтаксис.
Алуан Хаддад

11

Прийнята відповідь для мене не спрацювала, але я адаптував відповідь із властивості 'assign' не існує у типі 'ObjectConstructor', як це:

const changedFields = (<any>Object).entries(this.ngForm.form.controls)
                                   .filter(value => value[1].dirty);

Спільний доступ для тих, хто має таку ж ситуацію


2
Дякую Nguyen ...... Я використовую Angular 6 з машинописом 2.6.2, і це те, що мені вдалося. Я б дуже хотів, якби хтось міг це пояснити.
MichaelE

працював у мене на майданчику для машинопису. це якийсь серйозний вуду
Джуліан Суггет

У машинопису майданчику, ви не можете в даний час встановлено , --libтак що ви повинні використовувати , --targetщоб вказати , --libнеявно
Алуа Хаддад

Ти герой. Я не міг змінити lib, оскільки він генерується іншим додатком, де я не маю можливості змінити tsconfig.
Девід Фарінья,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.