Wie verwende ich Object.values ​​mit Typoskript?

135

Ich versuche, eine durch Kommas getrennte Zeichenfolge von einem Objekt zu bilden.

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

Wie geht das mit TypeScript?

eine Fehlerdatei erhalten:

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

Antworten:

106

Verwenden Sie stattdessen Object.keys.

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

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

const commaJoinedValues = values.join(",");
console.log(commaJoinedValues);
Holi-Java
quelle
90
Beachten Sie, dass dies eine Alternative ist (eine gute!), Keine tatsächliche Antwort darauf, wie ES7s Object.valuesin TS verwendet werden, um den Kompilierungsfehler des OP zu beheben . Dazu brauchen Sie einfach ES2017in Ihrer --libEinstellung.
Aaron Beall
4
@Aaron Ihre Lösung ist so komplex, dass jeder, der neu in Typoskript ist, nicht akzeptiert werden kann. Um sie zu kompilieren, müssen Sie ES2017lib hinzufügen und eine Polyfills-Bibliothek einschließen, in der Sie sie verwenden. Geben Sie unterschiedliche Antworten gegen verschiedene Personen.
Holi-Java
9
@ holi-jave Es ist nicht "meine Lösung", sondern nur die Funktionsweise von TS und noch nicht standardmäßigen JS-Funktionen, wie sie der OP versucht hat ES7/Object.values(). Vielleicht denken Sie, dass es komplex ist (ich bin nicht anderer Meinung), aber das ist nur die Natur des Versuchs, zukünftige Funktionen wie Object.values()heute zu nutzen. Es war schon immer so. Selbst Object.keys()wenn Sie auf ES3 abzielen oder IE8 unterstützen möchten (hoffentlich nicht mehr!), Sollte es im Allgemeinen eine gute Idee sein, die ES-Funktionen, die Browserunterstützung und das Polyfilling zu verstehen, wenn Sie sich in der Webentwicklung befinden!
Aaron Beall
@ Aaron Ich sage nicht, dass es komplex ist, aber für jemanden, der neu in Typoskript / Javascript ist, ist es komplexer und wird nicht akzeptiert.
Holi-Java
1
Lassen Sie uns diese Diskussion im Chat fortsetzen .
Holi-Java
223

Object.values()ist Teil von ES2017 , und der Kompilierungsfehler, den Sie erhalten, liegt darin, dass Sie TS für die Verwendung der ES2017-Bibliothek konfigurieren müssen. Sie verwenden wahrscheinlich die ES6- oder ES5-Bibliothek in Ihrer aktuellen TS-Konfiguration.

Lösung: Verwenden Sie es2017oder es2017.objectin Ihrer --libCompiler-Option .

Zum Beispiel mit tsconfig.json:

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

Beachten Sie, dass ES2017 mit Typoskript Targeting ist nicht polyfills im Browser für ES2017 emittieren (dh die oben löst Ihre Kompilierung Fehler, aber man kann immer noch auftreten Laufzeitfehler , da der Browser ES2017 nicht implementiert ), dann ist es an Ihnen, Ihr Projekt POLYfill Codieren Sie sich, wenn Sie möchten. Und da ist noch nicht gut von allen Browsern unterstützt (zum Zeitpunkt des Schreibens dieses Artikels) , die Sie auf jeden Fall eine polyfill: wird die Arbeit erledigen .Object.valuesObject.valuescore-js

Aaron Beall
quelle
1
@ErikvanVelzen Du hast die Antwort bearbeitet, um den Fall von zu ändern ES2017, es2017aber AFAIK das ist nicht notwendig, aber ich möchte immer lernen, gab es einen Grund für die Änderung?
Aaron Beall
2
^ Um meine eigene Frage zu beantworten: ES2017, DOM(Groß-) in dem aufgeführt ist tsc --initKommentar als die gültigen Werte und es funktioniert einwandfrei in den Compiler, aber das JSON Schema aufzählt nur die es2017, dom(klein geschrieben) Optionen, so JSON IDE / Linter Willen Flagge ES2017, DOMals ungültige Werte (obwohl sie gültig sind). Ein bisschen verwirrend.
Aaron Beall
Das war in der Tat der Grund. Es funktioniert in Großbuchstaben, wie Sie bemerken. tsc --helpzeigt jedoch Kleinbuchstaben
Erik van Velzen
Ist das Core-js nicht in Angular enthalten, wenn nicht, wie man diese Pollyfill hinzufügt?
Samiullah Khan
1
@ Totty.js Die in TS enthaltenen Bibliotheksdateien dienen nur zur Typprüfung. Mit anderen Worten, es werden keine JS-Bibliotheks-Polyfills für Dinge wie ausgegeben Object.values(). Mit anderen Worten, Sie können den Kompilierungsfehler umgehen, aber dennoch auf Laufzeitfehler stoßen, wenn Sie in einem Browser ausgeführt werden, der dies nicht hat Object.values().
Aaron Beall
18

Sie können dies Object.valuesin TypeScript verwenden, (<any>Object).values(data)wenn Sie aus irgendeinem Grund in tsconfig nicht auf ES7 aktualisieren können.

mtpultz
quelle
4
@ Aaron zum Zeitpunkt der Veröffentlichung gab es Kommentare, die darauf hinwiesen, dass Benutzer, die eine bestimmte Version von Angular verwendeten, Probleme hatten, die Bibliothek zu aktualisieren, wo sie nicht funktionierte. Deshalb habe ichif for some reason you can't update to ES7 in tsconfig
mtpultz
11

Anstatt

Object.values(myObject);

verwenden

Object["values"](myObject);

In Ihrem Beispielfall:

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

Dadurch wird der ts-Compilerfehler ausgeblendet.

Kian
quelle
1
du bist ein Genie (^ - ') b
harufumi.abe
Das Element hat implizit den Typ 'any', da der Typ 'ObjectConstructor' keine
Indexsignatur hat. Tts
6
Dies ist ein Missbrauch von TS. Sie sollten den Compiler mit der libEinstellung konfigurieren, die Ihre Verwendung widerspiegelt, und nicht absichtlich dem Compiler entkommen.
Aaron Beall
1
@ AaronBeall es ist eine gute Verwendung, wenn Sie aus irgendeinem Grund nicht auf es2017 aktualisieren können
Dino
@Dino Sie müssen nicht auf es2017 aktualisieren, sondern können mit core-js bis hinunter zu ES5 polyfill. TypeScript hat keine Laufzeit, die libEinstellung dient lediglich der korrekten Typprüfung.
Aaron Beall
11

Ich habe das Ziel in meinem erhöht tsconfig.json, um diese Funktion in TypeScript zu aktivieren

{
    "compilerOptions": {
        "target": "es2017",
        ......
    }
}
Lukas Ignatavičius
quelle
Das Ändern des Ziels ist keine Lösung, wenn Sie die Kompatibilität mit älteren Browsern beibehalten möchten. Typoskript muss in der Lage sein, eine ES2017-Syntax in ES2015 zu transpilieren.
Zufällig
4

Ich habe gerade genau dieses Problem mit Angular 6 mithilfe der CLI und der Arbeitsbereiche festgestellt, mit denen eine Bibliothek erstellt wurde ng g library foo.

In meinem Fall befand sich das Problem im tsconfig.lib.jsonOrdner "Bibliothek", der nicht es2017im libAbschnitt enthalten war.

Wenn Sie mit Angular 6 auf dieses Problem stoßen, müssen Sie nur sicherstellen, dass Sie tsconfig.lib.jsonund Ihre Anwendung aktualisiert werdentsconfig.json

Neil Stevens
quelle
Ich habe es2017 sowohl in tsconfig.lib als auch in tsconfig.json eingefügt, aber es wird immer noch der Fehler "Einträge existieren nicht für Objekt" angezeigt, wenn versucht wird, Einträge zu verwenden. Gibt es noch etwas, das ich ändern / aktualisieren sollte?
Maurice
Ich habe das Ziel in tsconfig.lib gerade jetzt auf es2017 geändert, immer noch der gleiche Fehler.
Maurice
2

Wenn meine tslintRegelkonfiguration hier immer die Zeile Object["values"](myObject)durch ersetztObject.values(myObject) .

Zwei Optionen, wenn Sie das gleiche Problem haben:

(Object as any).values(myObject)

oder

/*tslint:disable:no-string-literal*/
`Object["values"](myObject)`
kuncevic.dev
quelle
1
Warum sollten Sie jemals verwenden wollen Object["values"]?
Aaron Beall
-4

Der einfachste Weg ist, das Objectzu besetzen, wie folgt any:

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

Und voila - keine Kompilierungsfehler;)

Maksymilian Majer
quelle