Búsqueda de sitios web

javascript - La propiedad 'entries' no existe en el tipo 'ObjectConstructor'


Estoy trabajando en una implementación de ng2. Estoy usando la siguiente llamada a función para convertir un objeto en un array:

var authors = Object.entries(responseObject.Authors);

Esta es una función estándar de js. Sin embargo, el compilador de ts devuelve el siguiente error:

"Property 'entries' does not exist on type 'ObjectConstructor'"

Según una rápida búsqueda en Google, parece que la solución podría ser cambiar la propiedad target de compilerOptions de es5 a es6. Sin embargo, después de algunas investigaciones previas para un problema anterior, pensé que podía aprovechar la funcionalidad de es6 incluyendo la propiedad adicional "lib" en mi tsconfig.json a continuación:

  "compilerOptions": {
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "module": "commonjs",
    "noEmitOnError": true,
    "noImplicitAny": false,
    "outDir": "../Scripts/",
    "removeComments": false,
    "sourceMap": true,
    "target": "es5",
    "moduleResolution": "node",
    "lib": [
      "es2015",
      "dom"
    ]
  }

También intenté cambiar la propiedad target a es2015 y luego reconstruí el proyecto y ejecuté "typescriptUsingTsConfig" pero aún así obtengo el mismo error. ¿Alguna idea de lo que puedo hacer aquí para aprovechar la función Object.entries()?

Respuesta #1

Tienes toda la razón en que cambiar target es el enfoque equivocado y que cambiar lib es el enfoque correcto, sin embargo, has especificado la versión incorrecta del lenguaje. Según MDN, Object.entries se agregó oficialmente en la especificación ES2017.

"lib": ["es2017"]

es por lo tanto lo que debes especificar en su lugar*.

Si deseas agregar solo las declaraciones de los métodos de la función Object que fueron añadidos en ES2017, TypeScript te permite especificar un valor más granular.

"lib": ["es2017.object"]

Como señala Alexander Bird, por defecto, el valor implícito de la opción "lib" depende del valor especificado para "target" si está presente.

Por ejemplo:

"target": "es2017"

Provocará que el "lib.*" con el prefijo correspondiente se incluya por defecto a menos que se especifique explícitamente "lib".

Tenga en cuenta que probablemente desee agregar un polyfill de la propia implementación, como este, para asegurarse de que esto funcione en entornos más antiguos.

Nota: como alternativa, puedes especificar cualquier versión posterior

"lib": ["es2020"]

o incluso naturalmente

"lib": ["esnext"] 

Este último incluirá las declaraciones para las funciones más recientes de la biblioteca estándar conocidas por el lenguaje TypeScript. Como representa un objetivo en movimiento, esta opción debe usarse con cuidado, ya que el polyfill de todo el tiempo de ejecución correspondiente es por definición una tarea compleja que requerirá investigación y puede implicar cargar diferentes polyfills según su tiempo de ejecución objetivo.

Además, la naturaleza de arreglo de la opción "lib" te permite combinar múltiples valores para que coincidan con tu entorno de ejecución. Por ejemplo, para coincidir con navegadores web compatibles con es2015 con la adición de estos métodos de objeto tal como los proporciona un polyfill, puedes escribir

"lib": ["es2015", "es2017.object", "dom"]

Consulta el Manual de TypeScript para obtener detalles adicionales.

Nota: algunos comentaristas preguntaron por qué sería incorrecto cambiar --target en lugar de --lib, ya que ambos permitirían que el código pasara la verificación de tipos. La razón es que --target cambia cómo se transpila el código. Por ejemplo, "target": "es2017" significa que las funciones async no se transformarán para entornos más antiguos. Es incorrecto porque la intención era habilitar el uso de bibliotecas adicionales, no cambiar la sintaxis de salida, y por lo tanto es importante distinguir entre características sintácticas y características de la biblioteca.

Respuesta #2

La respuesta aceptada no funcionó para mí, pero adapté la respuesta de Propiedad 'assign' no existe en el tipo 'ObjectConstructor' de esta manera:

const changedFields = (<any>Object).entries(this.ngForm.form.controls)
                                   .filter(value => value[1].dirty);

Compartiendo para cualquiera que tenga la misma situación

Artículos relacionados