Властивість "призначити" не існує для типу "ObjectConstructor"


130

Я використовую TypeScript у своїй програмі, де я використовую функцію:

Object.assign(this.success, success.json())

Однак під час компіляції я отримую таку помилку:

 error TS2339: Property 'assign' does not exist on type 'ObjectConstructor'.

Чи маєте ви якесь уявлення, як я можу позбутися цієї помилки?


будь ласка, подумайте про зміну прийнятої відповіді - з тих пір було розміщено набагато кращі відповіді з більшою кількістю оновлень
— mindplay.dk

Відповіді:


129

Ви можете використовувати твердження типу , наприклад:

(<any>Object).assign(this.success, success.json())

30
Нічого собі, здається, це супер хакі.
— uksz

Добре, я бачу, що я заявляю, що "Об'єкт" має тип "будь-який".
— uksz

31
Хоча це здається рішенням, воно справді не повинно трактуватися як одне. Замість того, щоб просто додати двозначність і приховати помилки транспілера (що це робить), набагато краще, щоб насправді виправити їх і отримати корисні відгуки з консолі.
— Дмитро Паржицький

6
Це просто кастинг і приховування проблеми. Потенційно потрібно використовувати поліфауни в конкретних браузерах тощо. Це призведе до помилок, які працюють у деяких браузерах
— Том МакКарні,

3
Я б порадив усім, хто шукає тут, прокрутити трохи далі, де пояснюється, що додати до вашого, tsconfigщо є кращим рішенням, ніж це.
— mesqueeb

175

Налаштування:

Якщо ви використовуєте код VS (або ви бачите tsconfig.jsonфайл):

Ви повинні додати libвластивість до свого, tsconfig.jsonі тоді ваш редактор використовуватиме комплектні визначення типів сценарію, а також дасть вам інтелігенцію.

Просто додайте "lib": ["esnext", "dom"]свій tsconfig.jsonкод і перезапустіть код VS

{
    "compilerOptions": {
        // ...
        "target": "es5",
        "lib": ["esnext", "dom"]
        // ...
    }
}

Дивіться всі tsconfig.jsonваріанти тут .

Якщо ви використовуєте Visual Studio або MSBuild, включіть цей тег:

<TypeScriptLib>esnext, dom</TypeScriptLib>

Переглянути всі параметри компілятора MSBuild-компіляторів та використання тут .


Перевірте свою роботу:

Якщо ви налаштували ваш проект на використання вбудованих типів і перезапустили редактор, то ваш отриманий тип буде виглядати таким чином, а не типом, який anyви використовуєте Object.assign:

приклад коду 1


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

Зауважте, що якщо ви перекладаєте на ES5 або нижче та націляєте на IE11, вам потрібно буде включити polyfills, оскільки компілятор машинопису не буде включати поліфлі для вас.

Якщо ви хочете включити поліфіли (які ви повинні), то я рекомендую використовувати полі-заповнення core-js.

npm install --save core-js

або

yarn add core-js

Потім у точку входу у вашій програмі (наприклад /src/index.ts) додайте імпорт core-jsу верхній частині файлу:

import 'core-js';

Якщо ви не використовуєте менеджер пакунків, ви можете просто вставити наступний поліфайл, узятий з MDN, десь у вашому коді, який працює до використання Object.assign.

if (typeof Object.assign != 'function') {
  // Must be writable: true, enumerable: false, configurable: true
  Object.defineProperty(Object, "assign", {
    value: function assign(target, varArgs) { // .length of function is 2
      'use strict';
      if (target == null) { // TypeError if undefined or null
        throw new TypeError('Cannot convert undefined or null to object');
      }

      var to = Object(target);

      for (var index = 1; index < arguments.length; index++) {
        var nextSource = arguments[index];

        if (nextSource != null) { // Skip over if undefined or null
          for (var nextKey in nextSource) {
            // Avoid bugs when hasOwnProperty is shadowed
            if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {
              to[nextKey] = nextSource[nextKey];
            }
          }
        }
      }
      return to;
    },
    writable: true,
    configurable: true
  });
}

2
Я спробував "lib": ["es2015", "es2017", "dom"], але я все одно отримую " Властивості" значень "не існує для типу" ObjectConstructor ". , Я думаю, його немає в специфікації
— Нікос


Якщо випадково WebStorm видає помилку, вам потрібно встановити модуль Javascript.next тут: plugins.jetbrains.com/plugin/…
— Nicolas Boulet-Lavoie

Змінення tsconfig.json - це єдине вирішення, яке працює для мене. тобто додавання"lib": [ "es2015", "es2017", "dom" ]
— Danny Sofftie

2
@AQuirky TypeScriptTargetОпція змінює цільову версію EmcaScript (~ формальне ім'я JavaScript). FYI: ES2015не сумісний для IE11 (у випадку, якщо вам доведеться його підтримувати). Ви все ще можете встановити , TypeScriptTargetщоб в ES5той же час установка TypeScriptLibна DOM, ES2015досягнення тієї ж скрутне , а також зберігаючи сумісність з IE11 (але якщо ви не повинні підтримувати IE, а потім просто встановити TypeScriptTarget в ES2015).
— Ріко Калер

128

Це викликано тим, що ви використовуєте функцію ECMAScript 6 та орієнтуєтесь на ECMAScript 5 або 3. Найпростіший виправлення - встановити правильну ціль, наприклад, якщо ви використовуєте Grunt:

options: {
    target: 'es6'
}

змінити відповідну вкладку властивостей у Visual Studio або вручну, відредагувавши файл .csproj та знайшовши елемент TypeScriptTarget та перейшовши на ES6, наприклад:

<TypeScriptTarget>ES6</TypeScriptTarget>

Якщо вам потрібно націлити ES5, просто додайте наступне до свого коду TypeScript

declare interface ObjectConstructor {
    assign(target: any, ...sources: any[]): any;
}

Це об'єднує зайвий метод у вирішенні питання. Детальніше тут . Вам може знадобитися поліфайл, хоча, залежно від вимог сумісності вашого веб-переглядача - наприклад, цей від MDN :

if (typeof Object.assign != 'function') {
  (function () {
    Object.assign = function (target) {
      'use strict';
      if (target === undefined || target === null) {
        throw new TypeError('Cannot convert undefined or null to object');
      }

      var output = Object(target);
      for (var index = 1; index < arguments.length; index++) {
        var source = arguments[index];
        if (source !== undefined && source !== null) {
          for (var nextKey in source) {
            if (source.hasOwnProperty(nextKey)) {
              output[nextKey] = source[nextKey];
            }
          }
        }
      }
      return output;
    };
  })();
}

5
@JoeKeene Ця відповідь не вирішує проблему найкращим чином, як для TS 2.0+. Якщо ви орієнтуєтесь на ES5, то слід скористатися параметром --lib es2015компілятора. Моя проблема з вищевказаним підходом полягає в тому, що якщо ви declareвикористовуєте Object.assignфункцію замість вбудованої декларації, ви не отримаєте належного введення та документації. Вони додали --libопцію, тому вам не доведеться повторно заявляти інтерфейси, які вже є частиною стандарту.
— Rico Kahler

Для цього мені довелося додати декларацію інтерфейсу до .d.tsфайлу typing ( ), а не файл typecript ( ) .ts.
— Майк Чемберлен

@uksz Можливо, як це не хакі, це слід прийняти?
— Джейсон

Я змінив "target": "es5",до "target": "es6",в tsconfig.json. і це спрацювало (у)
— theapache64

1
Бо Object.valuesце повинно бути "target": "es2017", оскільки це верхній результат пошуку за тим самим кодом помилки.
— NobleUplift

3

Ви можете використовувати оператор розповсюдження, як у ES6

const obj = {...this.success,...success.json()};


1

Я додав типізації:

typings install dt~es6-shim --global --save

1
Схоже на ті ж типізації, на що я відповів? Або я щось пропускаю?
— Сергійс


-1

Я знаю, що це давно, але ось легке виправлення

(Object as any).assign(this.success, success.json())
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.