【问题标题】:Property 'assign' does not exist on type 'ObjectConstructor'“ObjectConstructor”类型上不存在属性“assign”
【发布时间】:2016-06-27 19:53:25
【问题描述】:

我在我的应用程序中使用 TypeScript,我使用函数:

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

但是,在编译过程中,我收到以下错误:

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

你知道我怎样才能摆脱这个错误吗?

【问题讨论】:

  • 请考虑更改已接受的答案 - 从那时起,已经发布了更好的答案和更多的赞成票。

标签: typescript


【解决方案1】:

配置:

如果您使用的是 VS 代码(或者如果您看到 tsconfig.json 文件):

您应该将lib 属性添加到您的tsconfig.json,然后您的编辑器将使用捆绑的打字稿类型定义并为您提供智能感知。

只需将 "lib": ["esnext", "dom"] 添加到您的 tsconfig.json 并重新启动 VS Code

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

查看所有tsconfig.json 选项here

如果您使用的是 Visual Studio 或 MSBuild,请包含此标记:

<TypeScriptLib>esnext, dom</TypeScriptLib>

查看所有 MSBuild typescript 编译器选项和用法here


检查你的工作:

如果您已将项目配置为使用内置类型并重新启动编辑器,那么当您使用 Object.assign 时,生成的类型将如下所示,而不是 any


关于 polyfill 和旧版浏览器兼容性的说明:

请注意,如果您要转译到 ES5 或更低版本并以 IE11 为目标,则需要包含 polyfill,因为 typescript 编译器不会为您包含 polyfill。

如果您想包含 polyfill(您应该这样做),那么我建议您使用 core-js 的 polyfill。

npm install --save core-js

yarn add core-js

然后在您的应用程序的入口点(例如/src/index.ts)在文件顶部添加core-js 的导入:

import 'core-js';

如果您没有使用包管理器,那么您只需将以下 polyfill taken from 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
  });
}

【讨论】:

  • 我尝试了 "lib":["es2015","es2017","dom"] 但我仍然得到 “ObjectConstructor”类型上不存在属性“值”。,我猜它不在规范中
  • @Nikos 你重启了vs代码吗? Object.values is in the spec.typescript has typings for it.
  • 如果万一WebStorm给你一个错误,你需要在这里安装Javascript.next插件:plugins.jetbrains.com/plugin/…
  • 修改 tsconfig.json 是唯一适合我的解决方法。即添加"lib": [ "es2015", "es2017", "dom" ]
  • @AQuirky TypeScriptTarget 选项更改 EmcaScript 的目标版本(~正式的 javascript 名称)。仅供参考:ES2015 与 IE11 不兼容(如果您必须支持它)。您仍然可以将TypeScriptTarget 设置为ES5,同时将TypeScriptLib 设置为DOM, ES2015 以实现相同的修复,同时还保持与IE11 的兼容性(但如果您不必支持IE,则只需设置TypeScriptTarget ES2015)。
【解决方案2】:

你可以使用type assertion,像这样:

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

【讨论】:

  • 哇,看起来超级 hacky.. 你能解释一下 (Object) 是做什么的吗?
  • 好的,我看到我声明 Object 的类型为 any。
  • 虽然这看起来像是一个解决方案,但它真的不应该被视为一个解决方案。与其简单地添加歧义并隐藏编译器错误(这样做),不如实际修复它们并从控制台获得有用的反馈。
  • 这只是投射和隐藏问题。您可能需要在特定浏览器等中使用 polyfills。这将导致在某些浏览器中运行错误
  • 我建议任何看这里的人向下滚动一点,它解释了要添加到您的 tsconfig 的内容,这是一个比这个更好的解决方案。
【解决方案3】:

这是由于您使用 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;
}

这合并了额外的方法,解决了问题。更多详情here。不过,您可能需要一个 polyfill,具体取决于您的 browser compatibility 要求 - 例如来自 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;
    };
  })();
}

【讨论】:

  • @JoeKeene 这个答案并没有像 TS 2.0+ 那样以最好的方式解决问题。如果你的目标是 ES5,那么你应该使用 --lib es2015 编译器选项。我对上述方法的问题是,如果您 declare Object.assign 函数而不是使用内置声明,那么您将无法获得正确的输入和文档。他们添加了--lib 选项,因此您不必重新声明已经是标准一部分的接口。
  • 为此,我必须将接口声明添加到类型 (.d.ts) 文件,而不是打字稿 (.ts) 文件中。
  • @uksz 也许这不是 hacky,应该被接受?
  • 我在tsconfig.json 中将"target": "es5", 更改为"target": "es6",。它起作用了(y)
  • 对于Object.values,它必须是"target": "es2017",因为这是相同错误代码的最高搜索结果。
【解决方案4】:

你可以像在 ES6 中一样使用扩展运算符

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

【讨论】:

    【解决方案5】:

    我添加了类型:

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

    【讨论】:

    • 看起来和我回复的打字一样?还是我错过了什么?
    【解决方案6】:

    为什么不使用扩展运算符?

    return {this.success, ...success.json() || {}};

    【讨论】:

    • 绝对优选使用传播,但在某些情况下不能Object.assign 覆盖,因为后者接受任意数量的对象。 return Object.assign({}, ...arrayOfObjects);.
    【解决方案7】:

    我在使用 @testing-library/react 使用 Jest 测试 React 应用程序时遇到了这个问题。我的解决方法是将以下内容添加到我的setupTests.ts

    declare global {
        interface Object {
            /**
             * Returns an array of values of the enumerable properties of an object
             * @param o Object that contains the properties and methods. This can be an object that you created or an existing Document Object Model (DOM) object.
             */
            values<T>(o: { [s: string]: T } | ArrayLike<T>): T[];
    
            /**
             * Returns an array of values of the enumerable properties of an object
             * @param o Object that contains the properties and methods. This can be an object that you created or an existing Document Object Model (DOM) object.
             */
            values(o: {}): any[];
    
            /**
             * Returns an array of key/values of the enumerable properties of an object
             * @param o Object that contains the properties and methods. This can be an object that you created or an existing Document Object Model (DOM) object.
             */
            entries<T>(o: { [s: string]: T } | ArrayLike<T>): [string, T][];
    
            /**
             * Returns an array of key/values of the enumerable properties of an object
             * @param o Object that contains the properties and methods. This can be an object that you created or an existing Document Object Model (DOM) object.
             */
            entries(o: {}): [string, any][];
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2019-02-17
      • 2018-01-07
      • 2018-10-13
      • 1970-01-01
      • 2016-12-16
      • 2020-10-02
      • 1970-01-01
      • 2021-01-09
      • 2021-07-10
      相关资源
      最近更新 更多