Свойство assign не существует для типа ObjectConstructor


130

Я использую TypeScript в своем приложении, где использую функцию:

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

Однако во время компиляции я получаю следующую ошибку:

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

Вы знаете, как мне избавиться от этой ошибки?


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

Ответы:


130

Вы можете использовать утверждение типа , например:

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

30
Вау, кажется супер хакерским ... Не могли бы вы объяснить, что делает (<any> Object)?
— uksz

Хорошо, я вижу, что объявляю, что у объекта есть тип.
— uksz

31
Хотя это кажется решением, на самом деле его не следует рассматривать как одно. Вместо того, чтобы просто добавить двусмысленность и скрыть ошибки транспилятора (что и происходит), гораздо лучше их исправить и получить полезную обратную связь с консоли.
— Дмитрий Паржицкий

6
Это просто наложение и сокрытие проблемы. Возможно, вам необходимо использовать полифиллы в определенных браузерах и т. Д. Это приведет к появлению ошибок в некоторых браузерах,
— Том МакКерни,

3
Я бы посоветовал любому, кто здесь смотрит, прокрутить немного дальше, где объясняется, что добавить к вашему, tsconfigчто является лучшим решением, чем это.
— mesqueeb

175

Настройка:

Если вы используете код VS (или видите tsconfig.jsonфайл):

Вы должны добавить libсвойство в свой, tsconfig.jsonи тогда ваш редактор будет использовать связанные определения типов машинописного текста, а также предоставит вам intellisense.

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

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

Смотрите все tsconfig.jsonварианты здесь .

Если вы используете Visual Studio или MSBuild, включите этот тег:

<TypeScriptLib>esnext, dom</TypeScriptLib>

Посмотреть все параметры компилятора машинописного текста MSBuild и его использование можно здесь .


Проверьте свою работу:

Если вы настроили свой проект на использование встроенных типов и перезапустили редактор, то ваш результирующий тип будет выглядеть так, а не тот, который был anyпри использовании Object.assign:

пример кода 1


Обратите внимание на полифиллы и совместимость с более старыми браузерами:

Обратите внимание, что если вы выполняете транспиляцию на ES5 или ниже и ориентируетесь на IE11, вам нужно будет включить полифиллы, потому что компилятор машинописного текста не будет включать полифиллы за вас.

Если вы хотите включить полифиллы (что вам следует), я бы рекомендовал использовать полифиллы 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/…
— Николя Буле-Лавуа,

Изменение tsconfig.json - единственное решение, которое мне подходит. т.е. добавление"lib": [ "es2015", "es2017", "dom" ]
— Дэнни Соффти

2
@AQuirky Параметр TypeScriptTargetизменяет целевую версию EmcaScript (~ формальное имя javascript). К вашему сведению: ES2015несовместимо с IE11 (если вам нужно его поддерживать). Вы все еще можете установить , TypeScriptTargetчтобы в ES5то же время установка TypeScriptLibна DOM, ES2015достижение той же затруднительное , а также сохраняя совместимость с IE11 (но если вы не должны поддерживать IE, а затем просто установить TypeScriptTarget в ES2015).
— Rico Kahler

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опцию, поэтому вам не нужно повторно объявлять интерфейсы, которые уже являются частью стандарта.
— Рико Калер

Чтобы это сработало, мне пришлось добавить объявление интерфейса в .d.tsфайл typings ( ), а не в .tsфайл typescript ( ).
— Майк Чемберлен

@uksz Может быть, так как это не взлом, его следует принять?
— Джейсон

Я перешел "target": "es5",на "target": "es6",в tsconfig.json. и это сработало (у)
— theapache64

1
Ведь Object.valuesэто должно быть так "target": "es2017", поскольку это лучший результат поиска с тем же кодом ошибки.
— NobleUplift


1

Я добавил шрифты:

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

1
Похоже, что я набрал то же самое, что и я? Или мне что-то не хватает?
— Sergejs


-1

Я знаю, что это было давно, но вот простое решение

(Object as any).assign(this.success, success.json())
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.