A propriedade 'assign' não existe no tipo 'ObjectConstructor'


130

Estou usando o TypeScript no meu aplicativo, onde uso a função:

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

No entanto, durante a compilação, eu recebo o seguinte erro:

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

Você tem alguma idéia de como posso me livrar desse erro?


considere alterar a resposta aceita - respostas muito melhores com mais votos positivos foram postadas desde então.
mindplay.dk

Respostas:


129

Você pode usar asserção de tipo , assim:

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

30
Uau, parece super hacky. Você poderia explicar o que (<any> Object) faz?
uksz

Tudo bem, vejo que estou declarando que Object tem o tipo any.
uksz

31
Embora isso pareça uma solução, realmente não deve ser tratado como um. Em vez disso, basta adicionar ambiguidade e ocultar erros do transpiler (o que ocorre), é muito melhor corrigi-los e obter feedback útil do console.
Dmitry Parzhitsky

6
Isso é apenas lançar e ocultar o problema. Você precisa potencialmente usar polyfills em navegadores específicos, etc. Isso resultará em erros em alguns navegadores
Tom McKearney /

3
Aconselho qualquer pessoa que esteja aqui a rolar um pouco mais a fundo, onde explica o que adicionar à sua, tsconfigque é uma solução melhor do que esta.
mesqueeb

175

Configure:

Se você estiver usando o código VS (ou se vir um tsconfig.jsonarquivo):

Você deve adicionar a libpropriedade ao seu tsconfig.jsone, em seguida, seu editor usará as definições de tipo de texto datilografado em pacote e também fornecerá inteligência.

Basta adicionar o "lib": ["esnext", "dom"]ao seu tsconfig.jsone reiniciar o VS Code

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

Veja todas as tsconfig.jsonopções aqui .

Se você estiver usando o Visual Studio ou MSBuild, inclua esta tag:

<TypeScriptLib>esnext, dom</TypeScriptLib>

Veja todas as opções e uso do compilador datilografado do MSBuild aqui .


Verifique seu trabalho:

Se você configurou seu projeto para usar os tipos internos e reiniciou o editor, o tipo resultante será semelhante a esse em vez do tipo anyquando você usar Object.assign:

exemplo de código 1


Nota sobre polyfills e compatibilidade com navegadores mais antigos:

Observe que se você estiver transpilando para o ES5 ou inferior e estiver direcionando o IE11, precisará incluir polyfills, porque o compilador de texto datilografado não incluirá os polyfills para você.

Se você deseja incluir os polyfills (o que você deve), recomendo o uso dos polyfills do core-js.

npm install --save core-js

ou

yarn add core-js

Em seguida, no ponto de entrada do seu aplicativo (por exemplo /src/index.ts), adicione a importação core-jsna parte superior do arquivo:

import 'core-js';

Se você não estiver usando um gerenciador de pacotes, basta colar o seguinte polyfill retirado do MDN em algum lugar do seu código que é executado antes do uso do 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
Eu tentei "lib": ["es2015", "es2017", "dom"], mas ainda recebo a propriedade 'values' não existe no tipo 'ObjectConstructor'. , Eu acho que não é na especificação
Nikos


Se, por acaso, o WebStorm fornecer um erro, você precisará instalar o plugin Javascript.next aqui: plugins.jetbrains.com/plugin/…
Nicolas Boulet-Lavoie 11/17

Modificar tsconfig.json é a única solução alternativa que funciona para mim. ou seja, adicionando #"lib": [ "es2015", "es2017", "dom" ]
Danny Sofftie

2
@AQuirky A TypeScriptTargetopção altera a versão de destino do EmcaScript (~ o ​​nome formal do javascript). FYI: ES2015não é compatível com o IE11 (caso você precise apoiá-lo). Você ainda pode definir TypeScriptTargetpara ES5além de definir TypeScriptLibpara DOM, ES2015conseguir o mesmo correção ao mesmo tempo que mantém a compatibilidade com IE11 (mas se você não tem que suportar o IE, em seguida, basta definir TypeScriptTarget a ES2015).
Rico Kahler 8/08

128

Isso é causado por você usar um recurso do ECMAScript 6 e direcionar o ECMAScript 5 ou 3. A correção mais fácil é definir o destino certo, por exemplo, se você estiver usando o Grunt:

options: {
    target: 'es6'
}

de alterar a guia de propriedades relevantes no Visual Studio ou manualmente, editando o arquivo .csproj e localizando o elemento TypeScriptTarget e alterando para ES6, por exemplo:

<TypeScriptTarget>ES6</TypeScriptTarget>

Se você precisar segmentar o ES5, basta adicionar o seguinte ao seu código TypeScript

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

Isso mescla o método extra, resolvendo o problema. Mais detalhes aqui . Você pode precisar de um polyfill, dependendo dos requisitos de compatibilidade do navegador - por exemplo, este da 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 Esta resposta não resolve o problema da melhor maneira que no TS 2.0+. Se você estiver segmentando o ES5, use a --lib es2015opção de compilador. Meu problema com a abordagem acima é que, se você usar declarea Object.assignfunção em vez de usar a declaração interna, não terá a digitação e a documentação adequadas. Eles adicionaram a --libopção para que você não precise declarar novamente as interfaces que já fazem parte do padrão.
Rico Kahler 02/02

Para que isso funcionasse, tive que adicionar a declaração da interface a um .d.tsarquivo typings ( ), em vez de um .tsarquivo typescript ( ).
Mike Chamberlain

@uksz Talvez, como não seja hacky, deva ser aceito?
Jason

Eu mudei "target": "es5",para "target": "es6",dentro tsconfig.json. e funcionou (y)
theapache64

1
Pois Object.values, deve ser "target": "es2017", já que este é o principal resultado da pesquisa para o mesmo código de erro.
NobleUplift

3

Você pode usar o operador spread como no ES6

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


1

Eu adicionei digitações:

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

1
Parece as mesmas tipografias que eu respondi? Ou estou faltando alguma coisa?
Sergejs 14/03

0

Por que não usar o operador de propagação?

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


-1

Eu sei que isso tem sido longo, mas aqui está uma solução fácil

(Object as any).assign(this.success, success.json())
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.