JavaScript

13 dez, 2019

Optional Chaining e null coalescing operator com TypeScript

Publicidade

Ultimamente estamos falando bastante das novas propostas do JavaScript no TC39 e novas features que estão saindo e sendo desenvolvidas a cada dia. Hoje vamos falar sobre uma das features mais esperadas para a linguagem que está presente em todo o lugar.

O que é o Optional Chaining?

Com certeza você já passou por uma situação destas: Imagine que você tem um objeto que possui uma série de parâmetros aninhados que podem ou não existir, por exemplo:

const artist = {
  name: 'Lucas', 
  age: 24,
  categories: ['rock', 'pop'],
  band: 'Red Hot Chilli Peppers',
  pets: [
    { name: 'Newton', type: 'cat' },
    { name: 'Panqueca', type: 'dog' }
  ]
}

Imagine que as propriedades pets e band podem ser nulos e vamos mais além, o caminho pets[0].name pode não existir, sendo um array do objetos do tipo { type: string } ou { name: string, type: string }.

Se fossemos fazer um tratamento para tudo isso teríamos que fazer algo deste tipo:

let bandName = null
if (artist && artist.band) {
  bandName = artist.band
}

let pets = []
if (artist && artist.pets) {
  pets = artist.pets.map(pet => {
    if (pet && pet.name) return pet.name
    return pet.type
  })
}

console.log(bandName, pets)

Claro que poderíamos reduzir para ternários desta forma:

let bandName = artist && artist.band ? artist.band : null

let pets = artist && artist.pets ? artist.pets.map(pet => pet && pet.name ? pet.name : pet.type) : []

Mas veja que estamos fazendo várias verificações para podermos, de fato, buscar o valor que queremos, não seria muito mais fácil se pudéssemos fazer isso de uma única vez?

A proposta do Optional Chaining é justamente transformar todos esses tratamentos em um novo operador ?., a ideia é que, quando uma chave de um objeto não for encontrado, o JS use o padrão de short circuit para poder retornar um undefined logo de cara, por exemplo, vamos traduzir o nosso exemplo com ternários para um exemplo com o Optional Chaining:

let bandName = artist?.band

let pets = artist?.pets?.map(pet => pet?.name || pet.type)

Viu como ficou tudo muito mais conciso e muito mais fácil de entender? Por padrão o Optional Chaining vai retornar undefined se um dos campos precedido por ?. não for encontrado, então vamos examinar nossos casos de retorno:

  1. Se ambos band e pet.name existirem, nosso retorno será Red Hot Chilli Peppers [Newton, Panqueca]
  2. Se band não existir nosso retorno será undefined [Newton, Panqueca]
  3. Se band existir e apenas um dos pets não tiver a propriedade name nosso retorno será Red Hot Chilli Peppers [cat, Panqueca]
  4. Se nem band e nenhum dos pets possuir name vamos ter undefined [cat, dog]
  5. Se nenhum deles existir vamos ter undefined undefined

Optional Chaining com Nullish Coalescing operator

Outra proposta que ficou bastante famosa é o Nullish Coalescing operator, o que ela faz é basicamente testar valores para null e undefined. Ao invés do nosso ternário ? que faz o teste para tudo que for falsy, ou seja, tudo que se resolve para false, vamos ter um operador ?? que só resolve true se o dado operado for null ou undefined.

E como isso nos ajuda? Veja que o Optional Chaining sempre retorna undefined quando ele não encontra um valor, então podemos fazer ternários utilizando expressões de duas partes ao invés do nosso condição ? true : false, poderemos fazer somente objeto?.chave ?? outra_coisa:
let bandName = artist?.band ?? 'Sem Banda'

let pets = artist?.pets?.map(pet => pet?.name || pet?.type) ?? 'Sem pets'

Agora, para o nosso caso 5 vamos ter Sem banda Sem pets como saída.

Optional Chaining e Nullish Coalescing com TypeScript

O TypeScript 3.7 já vem, por padrão, suportando estas novas propostas. Para podermos utilizar em nosso código, podemos simplesmente instalar o compilador do TS globalmente com npm i -g typescript@3.7. Porém, se você está usando o VSCode, deve imaginar que ele já vem com uma versão pré instalada do TypeScript, e ela não é a versão 3.7.

Temos duas opções nesse caso, podemos ou instalar em nosso projeto local com npm i typescript@3.7 -D e então clicarmos no canto inferior direito sobre a versão do TypeScript quando tivermos um projeto TS aberto no nosso editor e selecionar uma nova versão. Ou então podemos forçar com que o VSCode sempre utilize a versão mais nova do TypeScript.

Podemos realizar a segunda opção através da instalação de uma extensão chamada JavaScript and TypeScript Nightly, o que ela vai fazer é forçar com que seu VSCode sempre utilize a build da versão mais recente do repositório do TypeScript. Esta é uma extensão oficial feita pela Microsoft e é segura de ser utilizada em seus projetos.

Se você estiver utilizando babel, você pode instalar o plugin para optional chaining e registrá-lo na sua configuração

Conclusão

O Optional Chaining e o Nullish Coalescing operator não estão presentes em todos os browsers, enquanto o Nullish Coalescing não está ainda implementado em nenhum dos browsers maiores, o Optional Chaining já está funcionando na maioria dos browsers que rodam o V8 como engine, como o Chrome e o Opera.

Até mais!