Thuộc tính 'gán' không tồn tại trên loại 'ObjectConstructor'


130

Tôi đang sử dụng TypeScript trong ứng dụng của mình, nơi tôi sử dụng chức năng:

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

Tuy nhiên, trong quá trình biên dịch, tôi nhận được lỗi sau:

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

Bạn có biết làm thế nào tôi có thể thoát khỏi lỗi này?


vui lòng xem xét thay đổi câu trả lời được chấp nhận - câu trả lời tốt hơn nhiều với nhiều lượt upvote đã được đăng từ đó.
mindplay.dk

Câu trả lời:


129

Bạn có thể sử dụng xác nhận kiểu , như thế này:

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

30
Wow, có vẻ siêu hacky .. Bạn có thể giải thích (<any> Object) làm gì không?
uksz

Được rồi, tôi thấy rằng tôi đang tuyên bố rằng Object có kiểu bất kỳ.
uksz

31
Mặc dù đây có vẻ là một giải pháp, nhưng nó thực sự không nên được coi là một giải pháp. Thay vào đó chỉ đơn giản là thêm sự mơ hồ và ẩn các lỗi transpiler (điều này xảy ra), tốt hơn hết là thực sự sửa chúng và nhận phản hồi hữu ích từ bảng điều khiển.
Dmitry Parzhitsky

6
Đây chỉ là đúc và che giấu vấn đề. Bạn cần có khả năng sử dụng các polyfill trong các trình duyệt cụ thể, v.v ... Điều này sẽ dẫn đến lỗi chạy trong một số trình duyệt
Tom McKearney

3
Tôi sẽ khuyên bất cứ ai nhìn vào đây để cuộn xuống xa hơn một chút, nơi nó giải thích những gì cần thêm vào của bạn tsconfig, đó là một giải pháp tốt hơn so với giải pháp này.
mesqueeb

175

Cấu hình:

Nếu bạn đang sử dụng mã VS (hoặc nếu bạn thấy tsconfig.jsontệp):

Bạn nên thêm thuộc libtính vào tsconfig.jsonvà sau đó trình soạn thảo của bạn sẽ sử dụng các định nghĩa kiểu bản thảo được đóng gói và cũng cung cấp cho bạn thông tin.

Chỉ cần thêm mã "lib": ["esnext", "dom"]của bạn tsconfig.jsonvà khởi động lại Mã VS

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

Xem tất cả các tsconfig.jsontùy chọn ở đây .

Nếu bạn đang sử dụng Visual Studio hoặc MSBuild, hãy bao gồm thẻ này:

<TypeScriptLib>esnext, dom</TypeScriptLib>

Xem tất cả các tùy chọn và cách sử dụng trình biên dịch bản thảo MSBuild tại đây .


Kiểm tra công việc của bạn:

Nếu bạn đã cấu hình dự án của mình để sử dụng các loại tích hợp và khởi động lại trình soạn thảo của mình, thì loại kết quả của bạn sẽ trông như thế này thay vì loại anykhi bạn sử dụng Object.assign:

mã ví dụ 1


Lưu ý về polyfill và khả năng tương thích trình duyệt cũ hơn:

Lưu ý rằng nếu bạn đang dịch mã sang ES5 hoặc thấp hơn và đang nhắm mục tiêu IE11, bạn sẽ cần bao gồm các polyfill vì trình biên dịch bản thảo sẽ không bao gồm các polyfill cho bạn.

Nếu bạn muốn bao gồm các polyfill (mà bạn nên) thì tôi khuyên bạn nên sử dụng các polyfill của core-js.

npm install --save core-js

hoặc là

yarn add core-js

Sau đó, trong điểm vào trong ứng dụng của bạn (ví dụ /src/index.ts) thêm nhập core-jsvào ở đầu tệp:

import 'core-js';

Nếu bạn không sử dụng trình quản lý gói thì bạn chỉ có thể dán polyfill sau được lấy từ MDN ở một nơi nào đó trong mã của bạn chạy trước khi sử dụng 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
Tôi đã thử "lib": ["es2015", "es2017", "dom"] nhưng tôi vẫn nhận được các giá trị 'thuộc tính' không tồn tại trên loại 'ObjectConstructor'. , Tôi đoán nó không có trong thông số kỹ thuật
Nikos


Nếu bất kỳ trường hợp nào WebStorm gây ra lỗi cho bạn, bạn cần cài đặt plugin Javascript.next tại đây: plugins.jetbrains.com/plugin/ Kẻ
Nicolas Boulet-Lavoie

Sửa đổi tsconfig.json là cách giải quyết duy nhất phù hợp với tôi. tức là thêm"lib": [ "es2015", "es2017", "dom" ]
Danny Sofftie 28/03/18

2
@AQuirky TypeScriptTargetTùy chọn thay đổi phiên bản đích của EmcaScript (~ tên javascript chính thức). FYI: ES2015không tương thích với IE11 (trong trường hợp bạn phải hỗ trợ nó). Bạn vẫn có thể thiết lập TypeScriptTargetđể ES5đồng thời cũng thiết lập TypeScriptLibđể DOM, ES2015đạt được việc sửa chữa tương tự khi cũng còn tương thích với IE11 (nhưng nếu bạn không có để hỗ trợ IE, sau đó chỉ cần thiết TypeScriptTarget để ES2015).
Rico Kahler

128

Điều này là do bạn sử dụng tính năng ECMAScript 6 và nhắm mục tiêu ECMAScript 5 hoặc 3. Cách khắc phục dễ nhất là đặt đúng mục tiêu, ví dụ nếu bạn đang sử dụng Grunt:

options: {
    target: 'es6'
}

thay đổi tab thuộc tính có liên quan trong Visual Studio hoặc thủ công bằng cách chỉnh sửa tệp .csproj của bạn và tìm phần tử TypeScriptTarget và thay đổi thành ES6, ví dụ:

<TypeScriptTarget>ES6</TypeScriptTarget>

Nếu bạn cần nhắm mục tiêu ES5, thì chỉ cần thêm đoạn mã sau vào mã TypeScript của bạn

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

Điều đó hợp nhất các phương pháp bổ sung trong, giải quyết vấn đề. Thêm chi tiết tại đây . Mặc dù vậy, bạn có thể cần một polyfill, tùy thuộc vào yêu cầu tương thích trình duyệt của bạn - ví dụ: yêu cầu này từ 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 Câu trả lời này không giải quyết vấn đề theo cách tốt nhất như đối với TS 2.0+. Nếu bạn đang nhắm mục tiêu ES5 thì bạn nên sử dụng --lib es2015tùy chọn trình biên dịch. Vấn đề của tôi với cách tiếp cận trên là rằng nếu bạn declarecác Object.assignchức năng thay vì sử dụng được xây dựng trong tuyên bố sau đó bạn sẽ không nhận được gõ đúng đắn và tài liệu hướng dẫn. Họ đã thêm --libtùy chọn để bạn không phải khai báo lại các giao diện đã là một phần của tiêu chuẩn.
Rico Kahler

Để làm việc này, tôi phải thêm khai báo giao diện vào .d.tstệp typings ( ), thay vì tệp typcript ( .ts).
Mike Chamberlain

@uksz Có lẽ vì đây không phải là hacky nên nó được chấp nhận?
Jason

Tôi đổi "target": "es5",thành "target": "es6",trong tsconfig.json. và nó đã hoạt động (y)
theapache64

1
Đối với Object.values, nó phải như vậy "target": "es2017", vì đây là kết quả tìm kiếm hàng đầu cho cùng một mã lỗi.
NobleUplift

3

Bạn có thể sử dụng toán tử trải rộng như trong ES6

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


1

Tôi đã thêm các kiểu chữ:

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

1
Trông giống như những gì tôi đã trả lời? Hay tôi đang thiếu một cái gì đó?
Sergejs

0

Tại sao không sử dụng toán tử lây lan?

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


-1

Tôi biết điều này đã lâu nhưng đây là một sửa chữa dễ dàng

(Object as any).assign(this.success, success.json())
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.