Operadores Non-Null e Optional
No universo do Typescript, nós contamos com dois tipos de operadores que são bastante utilizados na maioria dos projetos, são eles:
!
(Non-null Assertion Operator)?
(Optional chaining e optional parameter)
Na lição de hoje, nós iremos aprender um pouco mais sobre o funcionamento de cada um deles 😉
Non-null Assertion Operator
O operador de ponto de exclamação (!
), também conhecido como Non-null Assertion Operator, é um operador usado para afirmar ao Typescript que você (desenvolvedor) tem a absoluta certeza de que uma expressão não é nula ou indefinida.
Antes de analisarmos o seu funcionamento, gostaria que você desse uma olhada no seguinte código abaixo:
let valor: string | null = "Micilini Roll";
console.log(valor.length);
No exemplo acima, estamos definindo uma variável (valor
) que pode receber um tipo string
ou null
.
E apesar de estarmos atribuíndo uma string
("Micilini Roll"
), o Typescript vai gerar o seguinte erro de compilação: Erro: Object is possibly 'null'.
Isso aconteceu, pois o Typescript identificou que nem sempre a variável valor
, irá armazenar um tipo string
, mas como também poderá armazenar um tipo null
.
E se por uma obra do acaso a nossa variável armazenar o tipo null
, isso pode quebrar a lógica do nosso código (e o Typescript não quer isso, certo?).
É por esse motivo que aquele erro é retornado 🤓 (Lembre-se que o Typescript é uma linguagem totalmente tipada).
Sendo assim, para corrigirmos aquele erro, temos duas alternativas, onde a primeira delas envolve a definição do Non-null Operator
:
let valor: string | null = "Micilini Roll";
console.log(valor!.length);
Com esse operador, nós estamos dizendo ao Typescript para ele não se preocupar, uma vez que nós temos certeza que de que o valor armazenado não é nulo.
Esse tipo de operador é utilizado com bastante frequência na manipulação de elementos HTML que podem ou não estar presentes na UI (famosa DOM).
Para exemplificar a sua utilização, vamos criar um novo arquivo chamado de index.html
com a seguinte estrutura:
<p id="nome">Micilini Roll</p>
Em seguida vamos criar o nosso index.ts
da seguinte forma:
const paragrafo = document.getElementById("nome").
console.log(paragrafo.innerText);
No comando acima, nós estamos selecionando o parágrafo cujo o id
é nome
, e em seguida estamos mostrando o valor existente dentro dele por meio do innerText
.
Olhando o comando assim por alto, não vemos nenhum problema aparente, certo? Só que... NÃO! Lembra que o Typescript é totalmente tipado? 😅
E apesar daquele código funcionar sem nenhum problema no Javascript, aqui no TS, ele não sabe se aquele parâgrafo vai existir ou não, e por esse motivo o compilador vai gerar erros e mensagens de alerta.
Nesse caso em específico, se temos certeza (absoluta) de que o parágrafo cujo id
é igual a nome
existir, podemos usar o operador de exclamação (!
) para isso:
const paragrafo = document.getElementById("nome").
console.log(paragrafo!.innerText);
Desse modo o TS vai parar de gerar mensagens de alerta 😉
Observação: quando utilizamos esse tipo de operador, estamos excluíndo a validação por inferência de tipo do Typescript, ou seja, nós estamos "desativando" a tipagem estática para aquela ocasião.
Portanto, ao usar o operador !
, você deve ter certeza absoluta de que a variável não será null
ou undefined
no momento de sua utilização, pois o TypeScript não fará verificação de nulidade para esses acessos após a aplicação do operador !
.
Optional chaining e optional parameter
Um outro operador bastante conhecido, é o ponto de interrogação ?
(Optional chaining e optional parameter).
Essa funcionalidade está presente tanto no Javascript quanto no Typescript, e usamos ela para lidar com situações onde você precisa acessar propriedades de objetos, que podem ser nulas ou indefinidas sem causar erros no compilador.
Antes da chegada desse operador, era comum nos depararmos com códigos como este abaixo:
// Exemplo sem Optional Chaining
if (obj && obj.prop && obj.prop.innerProp) {
// Faça algo com obj.prop.innerProp
}
Já com o Optional Chaining
, você pode simplificar isso usando o operador ?.
, na qual permite acessar propriedades profundas de um objeto de forma segura:
// Exemplo com Optional Chaining
if (obj?.prop?.innerProp) {
// Faça algo com obj.prop.innerProp
}
No caso do exemplo acima, se aquelas propriedades do obj
não existirem, a expressão retorna um undefined
sem lançar um erro na sua aplicação.
No tópico anterior, nós vimos a utilização do Non-null Operator no seguinte exemplo abaixo:
const paragrafo = document.getElementById("nome").
console.log(paragrafo.innerText);
No caso do código acima, nós também podemos usar o operador ?
, da seguinte forma:
const paragrafo = document.getElementById("nome").
console.log(paragrafo?.innerText);
Dessa modo, estamos dizendo ao Typescript que o parágrafo cujo o id
é igual a nome
, pode existir ou não, e se não existir retorna undefined
no console
em vez de gerar um erro na aplicação... ou:
const paragrafo = document.getElementById("nome").
if(paragrafo?.innerText){
console.log(paragrafo!.innerText);
}
Podemos verificar se ele existe para depois mostrar o seu valor.
Além disso, no tópico anterior nos deparamos com esse outro exemplo:
let valor: string | null = "Micilini Roll";
console.log(valor.length);
Alí também podíamos usar o ponto de interrogação ?
, da seguinte forma:
let valor: string | null = "Micilini Roll";
console.log(valor?.length);
O que verificaria se podemos acessar o length
antes de mostrá-lo.
Arquivos da lição
Os arquivos desta lição podem ser encontrados no repositório do GitHub por meio deste link.