Comment utiliser Object.values ​​avec dactylographié?

135

J'essaye de former une chaîne séparée par des virgules d'un objet,

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);

Comment faire cela avec TypeScript?

obtenir un fichier d'erreur:

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

Réponses:

106

en utilisant Object.keys à la place.

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

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

const commaJoinedValues = values.join(",");
console.log(commaJoinedValues);
holi-java
la source
90
Notez que c'est une alternative (une bonne!), Pas une réponse réelle sur la façon d'utiliser ES7 Object.valuesdans TS pour résoudre l'erreur de compilation de l'OP. Pour ce faire, vous avez simplement besoin ES2017dans votre --libcadre.
Aaron Beall
4
@Aaron votre solution est si complexe que quiconque est nouveau dans le typographie ne peut pas accepter, pour compiler, vous devez ajouter ES2017lib et inclure la bibliothèque polyfills là où l'utiliser.
holi-java
9
@ holi-jave Ce n'est pas "ma solution", c'est juste comment fonctionnent les fonctionnalités TS et JS non encore standard, comme la tentative d'utilisation de l'OP ES7/Object.values(). Peut-être pensez-vous que c'est complexe (je ne suis pas en désaccord), mais c'est juste la nature d'essayer d'utiliser des fonctionnalités futures comme Object.values()aujourd'hui. Ça a toujours été comme ça. Même Object.keys()si vous ciblez ES3 ou si vous souhaitez prendre en charge IE8 (j'espère que vous ne le faites plus!), Il est généralement recommandé de comprendre les fonctionnalités ES, la prise en charge du navigateur et le polyfilling si vous êtes en développement Web!
Aaron Beall
@Aaron Je ne suis pas dit que c'est complexe, mais pour quelqu'un de nouveau dans le typographie / javascript, c'est plus complexe et n'est pas accepté.
holi-java
1
Continuons cette discussion dans le chat .
holi-java
224

Object.values()fait partie de ES2017 , et l'erreur de compilation que vous obtenez est que vous devez configurer TS pour utiliser la bibliothèque ES2017. Vous utilisez probablement la bibliothèque ES6 ou ES5 dans votre configuration TS actuelle.

Solution: utilisez es2017ou es2017.objectdans votre --liboption de compilation .

Par exemple, en utilisant tsconfig.json:

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

Notez que le ciblage de ES2017 avec TypeScript n'émet pas de polyfills dans le navigateur pour ES2017 (ce qui signifie que ce qui précède résout votre erreur de compilation , mais vous pouvez toujours rencontrer une erreur d' exécution car le navigateur n'implémente pas ES2017 Object.values), c'est à vous de polyfill votre projet code vous-même si vous le souhaitez. Et comme il Object.valuesn'est pas encore bien pris en charge par tous les navigateurs (au moment d'écrire ces lignes), vous voulez vraiment un polyfill: core-jsfera le travail .

Aaron Beall
la source
1
@ErikvanVelzen Vous avez édité la réponse pour changer la casse de ES2017en es2017mais AFAIK ce n'est pas nécessaire, mais je veux toujours apprendre, y avait-il une raison pour le changement?
Aaron Beall
2
^ Pour répondre à ma propre question: ES2017, DOM(majuscule) est indiqué dans le tsc --initcommentaire que les valeurs valides et il fonctionne correctement dans le compilateur, mais le schéma JSON énumère uniquement les es2017, domoptions (minuscules), de sorte JSON IDE / linter signaleront ES2017, DOMcomme une valeur invalide (même si elles sont valides). Un peu déroutant.
Aaron Beall
C'était en effet la raison. Cela fonctionne en majuscules comme vous le notez. tsc --helpaffiche cependant des minuscules
Erik van Velzen
Le core-js n'est-il pas inclus dans angular, sinon comment ajouter ce pollyfill?
Samiullah Khan
1
@ Totty.js Les fichiers de bibliothèque que TS inclut sont uniquement destinés à la vérification de type , en d'autres termes, il n'émet en fait aucun polyfill de bibliothèque JS pour des choses comme Object.values(). En d'autres termes, vous pouvez contourner l'erreur de compilation mais toujours rencontrer des erreurs d'exécution si vous exécutez dans un navigateur qui n'a pas Object.values().
Aaron Beall
18

Vous pouvez utiliser Object.valuesdans TypeScript en faisant cela (<any>Object).values(data)si, pour une raison quelconque, vous ne pouvez pas mettre à jour vers ES7 dans tsconfig.

mtpultz
la source
4
@Aaron au moment de la publication, il y avait des commentaires indiquant que les personnes utilisant une version spécifique d'Angular avaient des problèmes pour mettre à jour la bibliothèque là où elle ne fonctionnait pas. C'est pourquoi je metsif for some reason you can't update to ES7 in tsconfig
mtpultz
11

Au lieu de

Object.values(myObject);

utilisation

Object["values"](myObject);

Dans votre exemple de cas:

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

Cela masquera l'erreur du compilateur ts.

Kian
la source
1
vous êtes génie (^ - ') b
harufumi.abe
L'élément a implicitement un type 'any' car le type 'ObjectConstructor' n'a pas d'index signature.ts (7017)
Tyguy7
6
C'est une mauvaise utilisation de TS. Vous devez configurer le compilateur avec le libparamètre pour refléter la façon dont vous l'utilisez, sans échapper intentionnellement au compilateur.
Aaron Beall
1
@AaronBeall c'est une bonne utilisation si pour une raison quelconque vous ne pouvez pas passer à es2017
Dino
@Dino Vous n'avez pas besoin de mettre à niveau vers es2017, vous pouvez utiliser core-js pour polyfill jusqu'à ES5. TypeScript n'a pas d'exécution, le libparamètre est juste pour obtenir la vérification de type correcte.
Aaron Beall
11

J'ai augmenté la cible dans mon tsconfig.jsonpour activer cette fonctionnalité dans TypeScript

{
    "compilerOptions": {
        "target": "es2017",
        ......
    }
}
Lukas Ignatavičius
la source
Changer la cible n'est pas une solution au cas où vous souhaiteriez conserver la compatibilité avec les anciens navigateurs. Typescript doit pouvoir transpiler une syntaxe ES2017 vers ES2015.
Aléatoire
4

Je viens de frapper ce problème exact avec Angular 6 en utilisant la CLI et les espaces de travail pour créer une bibliothèque en utilisant ng g library foo.

Dans mon cas, le problème se trouvait dans le tsconfig.lib.jsondossier de la bibliothèque qui ne figurait pas es2017dans la libsection.

Quiconque tombe sur ce problème avec Angular 6, il vous suffit de vous assurer que vous vous mettez à jour tsconfig.lib.jsonainsi que votre application.tsconfig.json

Neil Stevens
la source
J'ai mis es2017 dans tsconfig.lib et tsconfig.json, mais j'obtiens toujours l'erreur «Les entrées n'existent pas sur l'objet» lorsque j'essaie d'utiliser des entrées. Y a-t-il autre chose que je devrais changer / mettre à jour?
Maurice
J'ai changé la cible dans tsconfig.lib en es2017 tout à l'heure, toujours la même erreur.
Maurice
2

Avoir ma tslintconfiguration de règles ici en remplaçant toujours la ligne Object["values"](myObject)par Object.values(myObject).

Deux options si vous rencontrez le même problème:

(Object as any).values(myObject)

ou

/*tslint:disable:no-string-literal*/
`Object["values"](myObject)`
kuncevic.dev
la source
1
Pourquoi voudriez-vous jamais utiliser Object["values"]?
Aaron Beall
-4

Le moyen le plus simple est de lancer le Objectvers any, comme ceci:

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);

Et voila - pas d'erreurs de compilation;)

Maksymilian Majer
la source