La propriété 'assign' n'existe pas sur le type 'ObjectConstructor'


130

J'utilise TypeScript dans mon application, où j'utilise la fonction:

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

Cependant, lors de la compilation, je reçois l'erreur suivante:

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

Avez-vous une idée de comment puis-je me débarrasser de cette erreur?


Veuillez envisager de changer la réponse acceptée - de bien meilleures réponses avec plus de votes positifs ont été publiées depuis.
— mindplay.dk

Réponses:


129

Vous pouvez utiliser l' assertion de type , comme ceci:

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

30
Wow, ça semble super hacky ... Pouvez-vous expliquer ce que fait (<any> Object)?
— uksz

Très bien, je vois que je déclare que Object a le type any.
— uksz

31
Bien que cela semble être une solution, elle ne devrait vraiment pas être considérée comme telle. Plutôt que d'ajouter simplement de l'ambiguïté et de masquer les erreurs de transpilateur (ce que cela fait), il est de loin préférable de les corriger et d'obtenir des commentaires utiles de la console.
— Dmitry Parzhitsky

6
Il ne s'agit que de jeter et de cacher le problème. Vous devez potentiellement utiliser des polyfills dans des navigateurs spécifiques, etc. Cela entraînera des erreurs dans certains navigateurs
— Tom McKearney

3
Je conseillerais à tous ceux qui cherchent ici de faire défiler un peu plus bas où il explique ce qu'il faut ajouter à votre, tsconfigqui est une meilleure solution que celle-ci.
— mesqueeb

175

Configurer:

Si vous utilisez du code VS (ou si vous voyez un tsconfig.jsonfichier):

Vous devez ajouter la libpropriété à votre tsconfig.json, puis votre éditeur utilisera les définitions de type dactylographiées fournies et vous donnera également intellisense.

Ajoutez simplement le "lib": ["esnext", "dom"]à votre tsconfig.jsoncode VS et redémarrez-le

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

Voir toutes les tsconfig.jsonoptions ici .

Si vous utilisez Visual Studio ou MSBuild, incluez cette balise:

<TypeScriptLib>esnext, dom</TypeScriptLib>

Voir toutes les options et l'utilisation du compilateur MSBuild typescript ici .


Vérifie ton travail:

Si vous avez configuré votre projet pour utiliser les types intégrés et redémarré votre éditeur, votre type résultant ressemblera à ceci au lieu du type anylorsque vous utilisez Object.assign:

exemple de code 1


Remarque sur les polyfills et la compatibilité des anciens navigateurs:

Notez que si vous transpilez vers ES5 ou une version antérieure et ciblez IE11, vous devrez inclure des polyfills car le compilateur dactylographié n'inclura pas les polyfills pour vous.

Si vous souhaitez inclure les polyfills (ce que vous devriez), je vous recommande d'utiliser les polyfills de core-js.

npm install --save core-js

ou

yarn add core-js

Ensuite, dans le point d'entrée de votre application (par exemple /src/index.ts), ajoutez l'importation pour core-jsen haut du fichier:

import 'core-js';

Si vous n'utilisez pas de gestionnaire de packages, vous pouvez simplement coller le polyfill suivant extrait de MDN à un endroit de votre code qui s'exécute avant votre utilisation de 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
J'ai essayé "lib": ["es2015", "es2017", "dom"] mais j'obtiens toujours que la propriété 'values' n'existe pas sur le type 'ObjectConstructor'. , Je suppose que ce n'est pas dans les spécifications
— Nikos


Si par hasard WebStorm vous donne une erreur, vous devez installer le plugin Javascript.next ici: plugins.jetbrains.com/plugin/...
— Nicolas Boulet-Lavoie

La modification de tsconfig.json est la seule solution de contournement qui fonctionne pour moi. ie ajoutant"lib": [ "es2015", "es2017", "dom" ]
— Danny Sofftie

2
@AQuirky L' TypeScriptTargetoption change la version cible d'EmcaScript (~ le nom javascript formel). FYI: ES2015n'est pas compatible pour IE11 (au cas où vous deviez le supporter). Vous pouvez toujours définir TypeScriptTargetsur ES5tout en définissant TypeScriptLibsur DOM, ES2015pour obtenir le même correctif tout en restant compatible avec IE11 (mais si vous n'avez pas à prendre en charge IE, réglez simplement TypeScriptTarget sur ES2015).
— Rico Kahler

128

Cela est dû au fait que vous utilisez une fonctionnalité ECMAScript 6 et que vous ciblez ECMAScript 5 ou 3. La solution la plus simple consiste à définir la bonne cible, par exemple si vous utilisez Grunt:

options: {
    target: 'es6'
}

de modifier l'onglet de propriétés approprié dans Visual Studio, ou manuellement en modifiant votre fichier .csproj et en recherchant l'élément TypeScriptTarget et en passant à ES6, par exemple:

<TypeScriptTarget>ES6</TypeScriptTarget>

Si vous devez cibler ES5, ajoutez simplement ce qui suit à votre code TypeScript

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

Cela fusionne la méthode supplémentaire, résolvant le problème. Plus de détails ici . Cependant, vous aurez peut-être besoin d'un polyfill, en fonction des exigences de compatibilité de votre navigateur - par exemple celui de 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 Cette réponse ne résout pas le problème de la meilleure façon que pour TS 2.0+. Si vous ciblez ES5, vous devez utiliser l' --lib es2015option du compilateur. Mon problème avec l'approche ci-dessus est que si vous utilisez declarela Object.assignfonction au lieu d'utiliser la déclaration intégrée, vous n'obtiendrez pas une saisie et une documentation appropriées. Ils ont ajouté l' --liboption pour que vous n'ayez pas à re-déclarer les interfaces qui font déjà partie de la norme.
— Rico Kahler

Pour que cela fonctionne, j'ai dû ajouter la déclaration d'interface à un .d.tsfichier typings ( ), plutôt qu'à un .tsfichier typescript ( ).
— Mike Chamberlain

@uksz Peut-être que ce n'est pas du piratage, cela devrait être accepté?
— Jason

J'ai changé "target": "es5",pour "target": "es6",en tsconfig.json. et ça a marché (y)
— theapache64

1
Car Object.values, il doit l'être "target": "es2017", car il s'agit du premier résultat de recherche pour le même code d'erreur.
— NobleUplift

3

Vous pouvez utiliser l'opérateur de propagation comme dans ES6

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


1

J'ai ajouté des typages:

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

1
Ressemble à la même frappe que ce que j'ai répondu? Ou je manque quelque chose?
— Sergejs

0

Pourquoi ne pas utiliser l'opérateur de diffusion?

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


-1

Je sais que cela fait longtemps mais voici une solution facile

(Object as any).assign(this.success, success.json())
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.