Come usare Object.values ​​con typescript?


135

Sto cercando di formare una stringa separata da virgola da un oggetto,

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

Come fare questo con TypeScript?

ottenere un file di errore:

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

Risposte:


106

usando invece Object.keys.

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

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

const commaJoinedValues = values.join(",");
console.log(commaJoinedValues);

90
Si noti che questa è un'alternativa (una buona!), Non una risposta effettiva su come utilizzare ES7 Object.valuesin TS per risolvere l'errore di compilazione dell'OP. Per fare ciò hai semplicemente bisogno ES2017nella tua --libimpostazione.
Aaron Beall,

4
@Aaron la tua soluzione è così complessa che chiunque sia nuovo a dattiloscritto non può accettare, per compilare devi aggiungere ES2017lib e deve includere la libreria polyfill dove usarla. Dare una risposta diversa contro persone diverse è re.
holi-java,

9
@ holi-jave Non è "la mia soluzione", è solo il modo in cui funzionano TS e le funzionalità JS non ancora standard, come il tentativo di utilizzo dell'OP ES7/Object.values(). Forse pensi che sia complesso (non sono in disaccordo), ma è solo la natura del tentativo di utilizzare funzionalità future come Object.values()oggi. È sempre stato così. Anche se Object.keys()dovessi comunque eseguire il polyfill se scegli come target ES3 o se desideri supportare IE8 (speriamo che non lo faccia più!) In generale è una buona idea comprendere le funzionalità ES, il supporto del browser e il polyfilling se sei nello sviluppo web!
Aaron Beall,

@Aaron Non sono detto che sia complesso, ma per qualcuno che non conosce dattiloscritto / javascript è più complesso e non accettato.
holi-java,


224

Object.values()fa parte di ES2017 e l'errore di compilazione che si sta verificando è perché è necessario configurare TS per utilizzare la libreria ES2017. Probabilmente stai utilizzando la libreria ES6 o ES5 nella tua attuale configurazione TS.

Soluzione: utilizzare es2017o es2017.objectnella vostra --libopzione del compilatore .

Ad esempio, usando tsconfig.json:

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

Nota che il targeting ES2017 con dattiloscritto non non emette polyfills nel browser per ES2017 (cioè le risolve sopra la compilazione errore, ma è ancora possibile incontrare un runtime errore perché il browser non implementa ES2017 Object.values), tocca a voi per polyfill vostro progetto codifica te stesso se vuoi. E dal momento che Object.valuesnon è ancora ben supportato da tutti i browser (al momento della stesura di questo articolo) sicuramente vuoi un polyfill: core-jsfarà il lavoro .


1
@ErikvanVelzen Hai modificato la risposta per cambiare il caso ES2017in es2017ma AFAIK non è necessario, ma voglio sempre imparare, c'è stato un motivo per cambiare?
Aaron Beall

2
^ Per rispondere alla mia domanda: ES2017, DOM(maiuscolo) è elencato nel tsc --initcommento come i valori validi e funziona correttamente nel compilatore, ma la schema di JSON enumera solo le es2017, domopzioni (minuscolo), in modo da JSON IDE / linter volontà di bandiera ES2017, DOMcome valori non validi (anche se validi). Un po 'confuso.
Aaron Beall

In effetti questa era la ragione. Funziona in maiuscolo come si nota. tsc --helpmostra minuscole però
Erik van Velzen

Il core-js non è incluso in angolare, se non come aggiungere questo pollyfill?
Samiullah Khan,

1
@ Totty.js I file di libreria che TS include sono solo per il controllo del tipo , in altre parole in realtà non emette alcun polyfill di libreria JS per cose come Object.values(). In altre parole, puoi aggirare l'errore di compilazione ma comunque imbatterti in errori di runtime se esegui un browser che non ha Object.values().
Aaron Beall,

18

È possibile utilizzare Object.valuesin TypeScript in questo modo (<any>Object).values(data)se per qualche motivo non è possibile aggiornare a ES7 in tsconfig.


4
@Aaron al momento della pubblicazione c'erano commenti che indicavano che le persone che utilizzavano una versione specifica di Angular avevano problemi ad aggiornare la libreria in cui non funzionava. Ecco perché ho messoif for some reason you can't update to ES7 in tsconfig
mtpultz il

11

Invece di

Object.values(myObject);

uso

Object["values"](myObject);

Nel tuo esempio:

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

Ciò nasconderà l'errore del compilatore ts.


1
sei un genio (^ - ') b
harufumi.abe

L'elemento ha implicitamente un tipo 'qualsiasi' perché il tipo 'ObjectConstructor' non ha indice signature.ts (7017)
Tyguy7

6
Questo è un uso improprio di TS. È necessario configurare il compilatore con l' libimpostazione in modo da riflettere come lo si sta utilizzando, non sfuggire intenzionalmente al compilatore.
Aaron Beall,

1
@AaronBeall è utile se per qualche motivo non riesci a passare a es2017
Dino

@Dino Non è necessario eseguire l'aggiornamento a es2017, è possibile utilizzare core-js per eseguire il polyfill fino a ES5. TypeScript non ha runtime, l' libimpostazione è solo per ottenere il controllo del tipo corretto.
Aaron Beall

11

Ho aumentato il target nel mio tsconfig.jsonper abilitare questa funzione in TypeScript

{
    "compilerOptions": {
        "target": "es2017",
        ......
    }
}

La modifica della destinazione non è una soluzione nel caso in cui si desideri mantenere la compatibilità con i browser più vecchi. Typescript deve essere in grado di trascrivere una sintassi ES2017 in ES2015.
Casuale

4

Ho appena riscontrato questo esatto problema con Angular 6 utilizzando l'interfaccia della riga di comando e le aree di lavoro per creare una libreria utilizzando ng g library foo .

Nel mio caso il problema era nella tsconfig.lib.jsoncartella della libreria che non era stata es2017inclusa nel filelib sezione.

Chiunque si imbatta in questo problema con Angular 6 devi solo assicurarti di aggiornare te tsconfig.lib.jsone la tua applicazionetsconfig.json


ho inserito es2017 sia in tsconfig.lib che in tsconfig.json, ma continuo a ricevere l'errore "voci non esiste sull'oggetto" durante il tentativo di utilizzare le voci. C'è qualcos'altro che dovrei cambiare / aggiornare?
Maurice,

ho cambiato la destinazione in tsconfig.lib in es2017 proprio ora, sempre lo stesso errore.
Maurice,

2

Avere la mia tslintconfigurazione delle regole qui sostituendo sempre la linea Object["values"](myObject)conObject.values(myObject) .

Due opzioni se hai lo stesso problema:

(Object as any).values(myObject)

o

/*tslint:disable:no-string-literal*/
`Object["values"](myObject)`

1
Perché mai vorresti usare Object["values"]?
Aaron Beall,

-4

Il modo più semplice è lanciare il Objectto any, in questo modo:

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

E voilà - nessun errore di compilazione;)


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.