Właściwość „przypisać” nie istnieje w typie „ObjectConstructor”


138

Używam TypeScript w mojej aplikacji, gdzie używam funkcji:

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

Jednak podczas kompilacji pojawia się następujący błąd:

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

Czy masz pojęcie, jak mogę pozbyć się tego błędu?


1
prosimy o rozważenie zmiany zaakceptowanej odpowiedzi - od tego czasu pojawiły się o wiele lepsze odpowiedzi z większą liczbą głosów za.
— mindplay.dk

Odpowiedzi:


136

Możesz użyć asercji typu , na przykład:

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

31
Wow, wydaje się super hacky. Czy możesz wyjaśnić, co robi (<any> Object)?
— uksz

W porządku, widzę, że deklaruję, że Object ma typ any.
— uksz

32
Chociaż wydaje się to rozwiązaniem, tak naprawdę nie należy go traktować jako takiego. Zamiast po prostu dodać niejednoznaczność i ukryć błędy transpilera (co to robi), znacznie lepiej jest je naprawić i uzyskać przydatne informacje zwrotne z konsoli.
— Dima Parzhitsky

7
To tylko rzucanie i ukrywanie problemu. Trzeba potencjalnie wykorzystać polyfills w poszczególnych przeglądarkach, itd To spowoduje błędów prowadzących w niektórych przeglądarkach
— Tom McKearney

4
Każdemu, kto tu szuka, radzę przewinąć nieco dalej, gdzie wyjaśnia, co dodać do twojego, tsconfigco jest lepszym rozwiązaniem niż to.
— mesqueeb

183

Skonfiguruj:

Jeśli używasz kodu VS (lub jeśli widzisz tsconfig.jsonplik):

Powinieneś dodać tę libwłaściwość do swojego, tsconfig.jsona wtedy twój edytor użyje dołączonych definicji typów maszynopisu, a także zapewni ci inteligencję.

Po prostu dodaj "lib": ["esnext", "dom"]do swojego tsconfig.jsoni uruchom ponownie VS Code

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

Zobacz wszystkie tsconfig.jsonopcje tutaj .

Jeśli używasz programu Visual Studio lub MSBuild, dołącz ten tag:

<TypeScriptLib>esnext, dom</TypeScriptLib>

Zobacz wszystkie opcje kompilatora MSBuild i użycie tutaj .


Sprawdź swoją pracę:

Jeśli skonfigurowałeś projekt do korzystania z typów wbudowanych i zrestartowałeś edytor, wynikowy typ będzie wyglądał następująco, a nie typem, anygdy używasz Object.assign:

przykład kodu 1


Uwaga dotycząca wypełniaczy i zgodności ze starszymi przeglądarkami:

Zauważ, że jeśli transpilujesz do ES5 lub niższej i kierujesz się na IE11, będziesz musiał dołączyć polyfills, ponieważ kompilator maszynopisu nie będzie zawierał polyfillów.

Jeśli chcesz dołączyć polyfills (co powinieneś), polecam użycie polyfills core-js.

npm install --save core-js

lub

yarn add core-js

Następnie w punkcie wejścia w aplikacji (np. /src/index.ts) Dodaj import dla core-jsna górze pliku:

import 'core-js';

Jeśli nie używasz menedżera pakietów, możesz po prostu wkleić następujący wypełniacz pobrany z MDN w dowolnym miejscu w kodzie, który jest uruchamiany przed użyciem 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
Próbowałem „lib”: [„es2015”, „es2017”, „dom”], ale nadal otrzymuję „Wartości” właściwości nie istnieją w typie „ObjectConstructor”. , Myślę, że nie jest w specyfikacji
— Nikos


Jeśli przypadkiem WebStorm wyświetli błąd, musisz zainstalować wtyczkę Javascript.next tutaj: plugins.jetbrains.com/plugin/ ...
— Nicolas Boulet-Lavoie

Modyfikacja tsconfig.json jest jedynym rozwiązaniem, które działa w moim przypadku. tj. dodanie"lib": [ "es2015", "es2017", "dom" ]
— Danny Sofftie

2
@AQuirky Ta TypeScriptTargetopcja zmienia docelową wersję EmcaScript (~ formalna nazwa javascript). FYI: ES2015nie jest kompatybilny z IE11 (na wypadek, gdybyś musiał go obsługiwać). Nadal możesz ustawić TypeScriptTargetna, ES5jednocześnie ustawiając, TypeScriptLibaby DOM, ES2015osiągnąć tę samą poprawkę, jednocześnie zachowując zgodność z IE11 (ale jeśli nie musisz obsługiwać IE, po prostu ustaw TypeScriptTarget na ES2015).
— Rico Kahler

134

Jest to spowodowane korzystaniem z funkcji ECMAScript 6 i kierowaniem na ECMAScript 5 lub 3. Najłatwiejszym rozwiązaniem jest ustawienie właściwego celu, na przykład jeśli używasz Grunt:

options: {
    target: 'es6'
}

zmiany odpowiedniej karty właściwości w programie Visual Studio lub ręcznie, edytując plik .csproj i znajdując element TypeScriptTarget i zmieniając go na ES6, na przykład:

<TypeScriptTarget>ES6</TypeScriptTarget>

Jeśli chcesz kierować na ES5, po prostu dodaj następujące elementy do kodu TypeScript

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

To łączy dodatkową metodę, rozwiązując problem. Więcej szczegółów tutaj . Możesz jednak potrzebować polyfill, w zależności od wymagań dotyczących zgodności przeglądarki - na przykład ten z 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 Ta odpowiedź nie rozwiązuje problemu w najlepszy sposób jak w przypadku TS 2.0+. Jeśli celujesz w ES5, powinieneś użyć --lib es2015opcji kompilatora. Mój problem z podejściem powyższego jest, że jeśli funkcja zamiast za pomocą wbudowanego w deklaracji wtedy nie dostaniesz właściwego wpisywania i dokumentację. Dodali tę opcję, więc nie musisz ponownie deklarować interfejsów, które są już częścią standardu. declareObject.assign--lib
— Rico Kahler

Aby to zadziałało, musiałem dodać deklarację interfejsu do pliku typings ( .d.ts), a nie do pliku typescript ( ) .ts.
— Mike Chamberlain

@uksz Może skoro to nie jest hacky, to należy to zaakceptować?
— Jason

Zmieniłem "target": "es5",się "target": "es6",na tsconfig.json. i zadziałało (y)
— theapache64

1
Bo Object.valuestak musi być "target": "es2017", ponieważ jest to najwyższy wynik wyszukiwania dla tego samego kodu błędu.
— NobleUplift

3

Możesz użyć operatora spreadu, tak jak w ES6

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


1

Dodałem typy:

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

1
Wygląda na to, że te same wpisy, na które odpowiedziałem? Albo coś mi brakuje?
— Sergejs

1

Dlaczego nie skorzystać z operatora spreadu?

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


Zdecydowanie lepiej jest używać rozprzestrzeniania, ale nie może w niektórych scenariuszach, Object.assignponieważ ten ostatni akceptuje dowolną liczbę obiektów. return Object.assign({}, ...arrayOfObjects);.
— Aluan Haddad

-2

Wiem, że to trwało długo, ale tutaj jest łatwe rozwiązanie

(Object as any).assign(this.success, success.json())
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.