¿Cómo usar Object.values ​​con typecript?

135

Estoy tratando de formar una cadena separada por comas de un objeto,

const data = {"Ticket-1.pdf":"8e6e8255-a6e9-4626-9606-4cd255055f71.pdf","Ticket-2.pdf":"106c3613-d976-4331-ab0c-d581576e7ca1.pdf"};
const values = Object.values(data).map(x => x.substr(0, x.length - 4));
const commaJoinedValues = values.join(',');
console.log(commaJoinedValues);

¿Cómo hacer esto con TypeScript?

obteniendo un archivo de error:

severity: 'Error'
message: 'Property 'values' does not exist on type 'ObjectConstructor'.'
at: '216,27'
source: 'ts'
usuario2280016
fuente

Respuestas:

106

usando Object.keys en su lugar.

const data = {
  a: "first",
  b: "second",
};

const values = Object.keys(data).map(key => data[key]);

const commaJoinedValues = values.join(",");
console.log(commaJoinedValues);
holi-java
fuente
90
Tenga en cuenta que esta es una alternativa (¡buena!), No una respuesta real sobre cómo usar ES7 Object.valuesen TS para resolver el error de compilación del OP. Para hacer eso, simplemente necesita ES2017en su --libentorno.
Aaron Beall
44
@Aaron su solución es tan compleja que cualquier persona nueva en el mecanografiado no puede aceptar, para compilar debe agregar ES2017lib, y debe incluir la biblioteca polyfills donde usarla. Dar una respuesta diferente contra diferentes personas es el rey.
holi-java
9
@ holi-jave No es "mi solución", es solo cómo funcionan las funciones TS y JS aún no estándar, como el intento de uso de OP por parte de OP ES7/Object.values(). Tal vez piense que es complejo (no estoy en desacuerdo), pero esa es solo la naturaleza de tratar de usar características futuras como la Object.values()actual. Siempre ha sido así. Incluso Object.keys()debería estar polifundido si estaba apuntando a ES3 o si desea admitir IE8 (¡espero que ya no lo haga!) ¡Es una buena idea en general comprender las funciones de ES, el soporte del navegador y el polyfilling si está en desarrollo web!
Aaron Beall
@ Aaron No estoy dicho que sea complejo, pero para alguien nuevo en typecript / javascript es más complejo y no lo acepto.
holi-java
1
Continuemos esta discusión en el chat .
holi-java
224

Object.values() es parte de ES2017 , y el error de compilación que está obteniendo es porque necesita configurar TS para usar la biblioteca ES2017. Probablemente esté utilizando la biblioteca ES6 o ES5 en su configuración actual de TS.

Solución: use es2017o es2017.objecten su--lib opción de compilador .

Por ejemplo, usando tsconfig.json :

"compilerOptions": {
    "lib": ["es2017", "dom"]
}

Tenga en cuenta que la orientación ES2017 con mecanografiado no no emiten polyfills en el navegador para ES2017 (es decir, los resuelve por encima de su compilación de error, pero todavía se puede encontrar un tiempo de ejecución de error ya que el navegador no implementa ES2017 Object.values), le toca a usted para polyfill su proyecto codifícate si quieres. Y dado Object.valuesque todavía no está bien soportado por todos los navegadores (en el momento de escribir este artículo) definitivamente desea un polyfill: core-jshará el trabajo .

Aaron Beall
fuente
1
@ErikvanVelzen Editó la respuesta para cambiar el caso de ES2017a es2017pero AFAIK esto no es necesario, pero siempre quiero aprender, ¿hubo alguna razón para el cambio?
Aaron Beall el
2
^ Para responder a mi propia pregunta: ES2017, DOM(en mayúsculas) aparece en el tsc --initcomentario como los valores válidos y funciona correctamente en el compilador, pero el esquema JSON sólo enumera las es2017, domopciones (en minúsculas), por lo JSON IDE / bandera voluntad linter ES2017, DOMcomo valores inválidos (aunque sean válidos). Un poco confuso.
Aaron Beall el
De hecho esa fue la razón. Funciona en mayúscula como lo notas. tsc --helpsin embargo
Erik van Velzen
¿No se incluye core-js en angular, si no es así cómo agregar este pollyfill?
Samiullah Khan
1
@ Totty.js Los archivos de biblioteca que incluye TS son solo para verificación de tipo , en otras palabras, en realidad no emite ningún relleno de biblioteca JS para cosas como Object.values(). En otras palabras, puede evitar el error de compilación, pero aún puede encontrarse con errores de tiempo de ejecución si se ejecuta en un navegador que no tiene Object.values().
Aaron Beall
18

Puede usar Object.valuesTypeScript haciendo esto (<any>Object).values(data)si por alguna razón no puede actualizar a ES7 en tsconfig.

mtpultz
fuente
44
@Aaron en el momento de la publicación había comentarios que indicaban que las personas que usaban una versión específica de Angular tenían problemas para actualizar la biblioteca donde no funcionaba. Es por eso que pongoif for some reason you can't update to ES7 in tsconfig
mtpultz
11

En vez de

Object.values(myObject);

utilizar

Object["values"](myObject);

En su caso de ejemplo:

const values = Object["values"](data).map(x => x.substr(0, x.length - 4));

Esto ocultará el error del compilador ts.

Kian
fuente
1
eres genio (^ - ') b
harufumi.abe
El elemento tiene implícitamente un tipo 'any' porque el tipo 'ObjectConstructor' no tiene índice signature.ts (7017)
Tyguy7
66
Este es un mal uso de TS. Debe configurar el compilador con la libconfiguración para reflejar cómo lo está utilizando, no escapar intencionalmente del compilador.
Aaron Beall
1
@AaronBeall es un buen uso si por alguna razón no puede actualizar a es2017
Dino
@Dino No es necesario que actualices a es2017, puedes usar core-js para realizar polyfill hasta ES5. TypeScript no tiene tiempo de ejecución, la libconfiguración es solo para obtener la verificación de tipo correcta.
Aaron Beall
11

He aumentado el objetivo en mi tsconfig.jsonpara habilitar esta función en TypeScript

{
    "compilerOptions": {
        "target": "es2017",
        ......
    }
}
Lukas Ignatavičius
fuente
Cambiar el objetivo no es una solución en caso de que desee mantener la compatibilidad con navegadores más antiguos. Typecript tiene que poder transpilar una sintaxis de ES2017 a ES2015.
Aleatorio
4

Acabo de llegar a este problema exacto con Angular 6 usando la CLI y los espacios de trabajo para crear una biblioteca usando ng g library foo.

En mi caso, el problema estaba en la tsconfig.lib.jsoncarpeta de la biblioteca que no se había es2017incluido en la libsección.

Cualquiera que se encuentre con este problema con Angular 6 solo necesita asegurarse de actualizarlo tsconfig.lib.json, así como su aplicacióntsconfig.json

Neil Stevens
fuente
He puesto es2017 en tsconfig.lib y tsconfig.json, pero aún así aparece el error 'entradas no existe en el objeto' cuando intento usar entradas. ¿Hay algo más que deba cambiar / actualizar?
Maurice
Cambié el objetivo en tsconfig.lib a es2017 justo ahora, sigue siendo el mismo error.
Maurice
2

Tener mi tslintconfiguración de reglas aquí siempre reemplaza la línea Object["values"](myObject)conObject.values(myObject) .

Dos opciones si tiene el mismo problema:

(Object as any).values(myObject)

o

/*tslint:disable:no-string-literal*/
`Object["values"](myObject)`
kuncevic.dev
fuente
1
¿Por qué querrías usar alguna vez Object["values"]?
Aaron Beall
-4

La manera más simple es lanzar el Objectto any, así:

const data = {"Ticket-1.pdf":"8e6e8255-a6e9-4626-9606-4cd255055f71.pdf","Ticket-2.pdf":"106c3613-d976-4331-ab0c-d581576e7ca1.pdf"};
const obj = <any>Object;
const values = obj.values(data).map(x => x.substr(0, x.length - 4));
const commaJoinedValues = values.join(',');
console.log(commaJoinedValues);

Y listo - sin errores de compilación;)

Maksymilian Majer
fuente