Jak używać Object.values ​​z maszynopisem?

135

Próbuję utworzyć ciąg oddzielony przecinkami z obiektu,

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

Jak to zrobić z TypeScript?

pobieranie pliku błędu:

severity: 'Error'
message: 'Property 'values' does not exist on type 'ObjectConstructor'.'
at: '216,27'
source: 'ts'
user2280016
źródło

Odpowiedzi:

106

używając zamiast tego 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
źródło
90
Zauważ, że jest to alternatywa (dobra!), A nie faktyczna odpowiedź na temat używania ES7 Object.valuesw TS do rozwiązania błędu kompilacji OP. Aby to zrobić, po prostu potrzebujesz ES2017w swoim --libotoczeniu.
Aaron Beall
4
@Aaron Twoje rozwiązanie jest tak złożone, że nikt, kto nie zna maszynopisu, nie może go zaakceptować, aby skompilować, musisz dodać ES2017bibliotekę lib i musi zawierać bibliotekę polyfills, jeśli jej używasz. Daj inną odpowiedź przeciwko różnym ludziom.
holi-java
9
@ holi-jave To nie jest „moje rozwiązanie”, tylko sposób działania TS i niestandardowych jeszcze funkcji JS, na przykład próba użycia przez OP ES7/Object.values(). Może myślisz, że to skomplikowane (nie zgadzam się), ale taka jest natura prób wykorzystania przyszłych funkcji, tak jak Object.values()dzisiaj. Zawsze tak było. Nawet Object.keys()powinno być wypełnione w pełni, jeśli celujesz w ES3 lub chcesz obsługiwać IE8 (miejmy nadzieję, że już nie!). Ogólnie rzecz biorąc, dobrym pomysłem jest zrozumienie funkcji ES, obsługi przeglądarek i wypełniania polyfilling, jeśli tworzysz strony internetowe!
Aaron Beall
@Aaron Nie powiedziałem, że jest skomplikowany, ale dla kogoś nowego w maszynopisie / javascript jest bardziej złożony i nie jest akceptowany.
holi-java
1
Daj nam kontynuować tę dyskusję w czacie .
holi-java
224

Object.values()jest częścią ES2017 , a błąd kompilacji, który otrzymujesz, wynika z konieczności skonfigurowania TS do korzystania z biblioteki ES2017. Prawdopodobnie używasz biblioteki ES6 lub ES5 w bieżącej konfiguracji TS.

Rozwiązanie: użyj es2017lub es2017.objectw --libopcji kompilatora .

Na przykład używając tsconfig.json:

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

Należy pamiętać, że kierowanie ES2017 z maszynopis nie nie emitują polyfills w wyszukiwarce ES2017 (czyli powyższe rozwiązuje kompilacji błąd, ale nadal można napotkać w czasie wykonywania błąd, ponieważ przeglądarka nie implementuje ES2017 Object.values), to do ciebie, aby PolyFill projekt zaprogramuj się, jeśli chcesz. A ponieważ Object.valuesnie jest jeszcze dobrze obsługiwany przez wszystkie przeglądarki (w momencie pisania tego tekstu), na pewno chcesz mieć wypełnienie: core-jswykona zadanie .

Aaron Beall
źródło
1
@ErikvanVelzen Edytowałeś odpowiedź, aby zmienić wielkość liter ES2017na, es2017ale AFAIK nie jest to konieczne, ale zawsze chcę się dowiedzieć, czy był powód zmiany?
Aaron Beall
2
^ Aby odpowiedzieć na moje własne pytanie: ES2017, DOM(wielka litera) jest wymieniony w tsc --initkomentarzu co prawidłowych wartości i działa poprawnie w kompilator, ale schemat JSON wymienia tylko es2017, domopcje (małe litery), więc JSON IDE / LINTER oznaczy ES2017, DOMjak nieprawidłowe wartości (nawet jeśli są prawidłowe). Trochę zagmatwane.
Aaron Beall
Rzeczywiście, to był powód. Jak zauważyłeś, działa wielkimi literami. tsc --helpwyświetla jednak małe litery
Erik van Velzen
Czy core-js nie jest zawarty w angular, jeśli nie, to jak dodać to pollyfill?
Samiullah Khan
1
@ Totty.js Pliki bibliotek, które zawiera TS, służą tylko do sprawdzania typu , innymi słowy, w rzeczywistości nie emitują żadnych wypełnień bibliotek JS do rzeczy takich jak Object.values(). Innymi słowy, możesz obejść błąd kompilacji, ale nadal napotykasz błędy czasu wykonania, jeśli uruchomisz przeglądarkę, która nie ma Object.values().
Aaron Beall
18

Możesz użyć Object.valuesw TypeScript, robiąc to, (<any>Object).values(data)jeśli z jakiegoś powodu nie możesz zaktualizować do ES7 w tsconfig.

mtpultz
źródło
4
@Aaron w momencie publikacji pojawiały się komentarze wskazujące, że osoby korzystające z określonej wersji Angular miały problemy z aktualizacją biblioteki, gdzie nie działała. Dlatego umieściłemif for some reason you can't update to ES7 in tsconfig
mtpultz
11

Zamiast

Object.values(myObject);

posługiwać się

Object["values"](myObject);

W Twoim przypadku:

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

Spowoduje to ukrycie błędu kompilatora ts.

Kian
źródło
1
jesteś geniuszem (^ - ') b
harufumi.abe
Element niejawnie ma typ „dowolny”, ponieważ typ „ObjectConstructor” nie ma podpisu indeksu.
T
6
To jest niewłaściwe użycie TS. Należy skonfigurować kompilator z libustawieniem, aby odzwierciedlić sposób jego używania, a nie celowo uciekać przed kompilatorem.
Aaron Beall
1
@AaronBeall to dobry użytek, jeśli z jakiegoś powodu nie możesz uaktualnić do es2017
Dino
@Dino Nie musisz aktualizować do es2017, możesz użyć core-js do polyfill aż do ES5. TypeScript nie ma środowiska uruchomieniowego, libustawienie służy tylko do uzyskania prawidłowego sprawdzania typu.
Aaron Beall
11

Zwiększyłem cel w moim, tsconfig.jsonaby włączyć tę funkcję w TypeScript

{
    "compilerOptions": {
        "target": "es2017",
        ......
    }
}
Lukas Ignatavičius
źródło
Zmiana celu nie jest rozwiązaniem, jeśli chcesz zachować zgodność ze starszymi przeglądarkami. Maszynopis musi być w stanie przetransponować składnię ES2017 do ES2015.
Losowo
4

Właśnie trafiłem na ten konkretny problem w Angular 6, używając interfejsu wiersza polecenia i obszarów roboczych do tworzenia biblioteki przy użyciu ng g library foo.

W moim przypadku problem znajdował się tsconfig.lib.jsonw folderze biblioteki, którego nie ma es2017w libsekcji.

Każdy, kto natknie się na ten problem w Angular 6, musi tylko upewnić się, że zaktualizowałeś siebie tsconfig.lib.jsoni swoją aplikacjętsconfig.json

Neil Stevens
źródło
Umieściłem es2017 zarówno w tsconfig.lib, jak i tsconfig.json, ale nadal pojawia się błąd „Wpisy nie istnieją w obiekcie” podczas próby użycia wpisów. Czy jest jeszcze coś, co powinienem zmienić / zaktualizować?
Maurice
Zmieniłem cel w tsconfig.lib na es2017 właśnie teraz, wciąż ten sam błąd.
Maurice
2

Mając moją tslintkonfigurację zasadami tutaj zawsze zastąpienie linii Object["values"](myObject)z Object.values(myObject).

Dwie opcje, jeśli masz ten sam problem:

(Object as any).values(myObject)

lub

/*tslint:disable:no-string-literal*/
`Object["values"](myObject)`
kuncevic.dev
źródło
1
Dlaczego miałbyś kiedykolwiek chcieć używać Object["values"]?
Aaron Beall
-4

Najprostszym sposobem jest rzutowanie Objectdo any, na przykład:

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

I voila - brak błędów kompilacji;)

Maksymilian Majer
źródło