Como usar Object.values ​​com texto datilografado?

135

Estou tentando formar uma string separada por vírgula de um 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);

Como fazer isso com o TypeScript?

obtendo um arquivo de erro:

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

Respostas:

106

usando 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
fonte
90
Observe que essa é uma alternativa (boa!), Não uma resposta real sobre como usar os ES7 Object.valuesno TS para resolver o erro de compilação do OP. Para fazer isso, você simplesmente precisa ES2017em sua --libconfiguração.
Aaron Beall 23/03
4
@Aaron, sua solução é tão complexa que qualquer pessoa iniciante no datilografado não pode aceitar; para compilar, você deve adicionar ES2017lib e incluir a biblioteca polyfills onde usá-la. Dê uma resposta diferente a pessoas diferentes.
Holi-java
9
@ holi-jave Não é "minha solução", é apenas como os recursos TS e JS ainda não-padrão funcionam, como a tentativa de uso do OP ES7/Object.values(). Talvez você pense que é complexo (não discordo), mas essa é apenas a natureza de tentar usar recursos futuros como Object.values()hoje. Sempre foi assim. Ainda Object.keys()deve ser preenchido com polifilme se você estava direcionado para o ES3 ou deseja oferecer suporte ao IE8 (espero que não exista mais!) Em geral, é uma boa idéia entender os recursos de ES, o suporte ao navegador e o preenchimento com polifilling se você estiver em desenvolvimento na Web!
Aaron Beall 24/03
@ Aaron Eu não disse que é complexo, mas para alguém novo no texto / javascript é mais complexo e não é aceito.
Holi-java
1
Vamos continuar esta discussão no chat .
Holi-java
224

Object.values()faz parte do ES2017 , e o erro de compilação que você está recebendo é porque você precisa configurar o TS para usar a biblioteca ES2017. Você provavelmente está usando a biblioteca ES6 ou ES5 na sua configuração atual do TS.

Solução: use es2017ou es2017.objectna sua --libopção de compilador .

Por exemplo, usando tsconfig.json:

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

Nota que a segmentação ES2017 com texto datilografado que não emitem polyfills no navegador para ES2017 (ou seja, os resolve acima de sua compilação de erro, mas você ainda pode encontrar um tempo de execução de erro porque o navegador não implementa ES2017 Object.values), é até você para polyfill seu projeto codifique-se, se quiser. E como Object.valuesainda não é bem suportado por todos os navegadores (no momento da redação deste documento), você definitivamente deseja um polyfill: core-jsfará o trabalho .

Aaron Beall
fonte
1
@ErikvanVelzen Você editou a resposta para alterar o caso ES2017da es2017mas AFAIK isso não é necassary, mas eu sempre quero aprender, havia uma razão para a mudança?
Aaron Beall
2
^ Para responder a minha própria pergunta: ES2017, DOM(maiúsculas) está listado no tsc --initcomentário como os valores válidos e ele funciona corretamente no compilador, mas o esquema JSON enumera apenas as es2017, domopções (minúsculas), de modo JSON IDE / bandeira vontade linter ES2017, DOMcomo valores inválidos (mesmo que válidos). Um pouco confuso.
Aaron Beall
De fato, esse foi o motivo. Funciona em maiúsculas, como você observa. tsc --helpexibe letras minúsculas
Erik van Velzen
O core-js não está incluído no angular? Se não, é assim que se adiciona esse pollyfill?
Samiullah Khan
1
@ Totty.js Os arquivos de biblioteca que o TS inclui são apenas para verificação de tipo ; em outras palavras, ele não emite nenhum polyfills de biblioteca JS para coisas do tipo Object.values(). Em outras palavras, você pode contornar o erro de compilação, mas ainda assim ocorrer erros de tempo de execução se você executar em um navegador que não possui Object.values().
Aaron Beall
18

Você pode usar o Object.valuesTypeScript fazendo isso (<any>Object).values(data)se, por algum motivo, não puder atualizar para o ES7 no tsconfig.

mtpultz
fonte
4
A @Aaron no momento da publicação havia comentários indicando que as pessoas que usam uma versão específica do Angular tiveram problemas para atualizar a lib onde ela não estava funcionando. É por isso que eu coloqueiif for some reason you can't update to ES7 in tsconfig
mtpultz 20/03/19
11

Ao invés de

Object.values(myObject);

usar

Object["values"](myObject);

No seu caso de exemplo:

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

Isso ocultará o erro do compilador ts.

Kian
fonte
1
Você é um gênio (^ - ') b
harufumi.abe 18/11/18
Elemento tem implicitamente um 'qualquer' tipo porque o tipo 'ObjectConstructor' não tem signature.ts índice (7017)
Tyguy7
6
Este é um mau uso do TS. Você deve configurar o compilador com a libconfiguração para refletir como o está usando, e não escapar intencionalmente do compilador.
Aaron Beall
1
@AaronBeall é um bom uso, se por algum motivo você não pode atualizar para es2017
Dino
@Dino Você não precisa atualizar para o es2017, pode usar o core-js para polyfill até o ES5. O TypeScript não possui tempo de execução, a libconfiguração é apenas para obter a verificação de tipo correta.
Aaron Beall
11

tsconfig.jsonAumentei o alvo no meu para ativar esse recurso no TypeScript

{
    "compilerOptions": {
        "target": "es2017",
        ......
    }
}
Lukas Ignatavičius
fonte
Alterar o destino não é uma solução, caso você queira manter a compatibilidade com navegadores mais antigos. O texto datilografado deve poder transpilar uma sintaxe do ES2017 para o ES2015.
Aleatório
4

Acabei de acertar esse problema exato com o Angular 6 usando a CLI e os espaços de trabalho para criar uma biblioteca usando ng g library foo .

No meu caso, o problema estava na tsconfig.lib.jsonpasta da biblioteca que não havia es2017incluído no arquivolib seção.

Se você se deparar com esse problema com o Angular 6, basta garantir que você atualize você tsconfig.lib.jsone seu aplicativotsconfig.json

Neil Stevens
fonte
Eu coloquei es2017 em tsconfig.lib e tsconfig.json, mas ainda assim recebo o erro 'entradas não existem no erro Objeto' ao tentar usar entradas. Há mais alguma coisa que eu deva alterar / atualizar?
Maurice
Eu mudei o alvo no tsconfig.lib para es2017 agora, ainda o mesmo erro.
Maurice
2

Ter minhas tslintregras de configuração aqui sempre substituindo a linha Object["values"](myObject)por Object.values(myObject).

Duas opções se você tiver o mesmo problema:

(Object as any).values(myObject)

ou

/*tslint:disable:no-string-literal*/
`Object["values"](myObject)`
kuncevic.dev
fonte
1
Por que você gostaria de usar Object["values"]?
Aaron Beall
-4

A maneira mais simples é converter o Objectpara any, assim:

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 voila - sem erros de compilação;)

Maksymilian Majer
fonte