Artigo original: JavaScript TypeOf – How to Check the Type of a Variable or Object in JS
Tipos de dados e verificação de tipos são aspectos fundamentais em qualquer linguagem de programação. Muitas delas, como o Java, têm verificação de tipos estrita. Isso significa que, se uma variável é definida com um tipo específico, ela pode conter valores somente daquele tipo.
O JavaScript, entretanto, é uma linguagem fracamente (ou dinamicamente) tipada. Isso quer dizer que uma variável pode conter valores de qualquer tipo. O código em JavaScript pode ser executado assim:
let one = 1;
one = 'um';
one = true;
one = Boolean(true);
one = String('É possível');
Com isso em mente, é fundamental conhecer o tipo da variável em qualquer momento dado.
O tipo de uma variável é determinado pelo tipo do valor atribuído a ela. O JavaScript tem um operador especial, chamado typeof, que permite que você obtenha o tipo de qualquer valor.
Neste artigo, aprenderemos sobre como typeof é utilizado, juntamente com alguns cuidados que você deve ter.
Tipos de dados em JavaScript
Vamos dar uma olhada rápida nos tipos de dados em JavaScript antes de entrarmos mais a fundo no operador typeof.
Em JavaScript, existem sete tipos primitivos. Um tipo primitivo é qualquer coisa que não seja um objeto. Esses tipos em JavaScript são:
- String
- Number (número)
- BigInt (número inteiro "grande")
- Symbol (símbolo)
- Boolean (booleano)
- undefined (variável de tipo não definido - pois o valor ainda não foi definido)
- null (tipo nulo)
Todo o resto são objetos (em inglês, object) – incluindo array e function. Um objeto é uma coleção de pares chave-valor.
O operador typeof em JavaScript
O operador typeof recebe apenas um operando (é um operador unário). Ele avalia o tipo do operando e retorna o resultado como uma string. É assim que utilizamos o operador ao avaliar o tipo de um número, como, por exemplo, 007.
typeof 007; // retorna 'number' - um número
Há uma sintaxe alternativa para o operador typeof, onde você pode usá-lo como uma function:
typeof(operando)
Essa sintaxe é útil quando você deseja avaliar uma expressão em vez de um valor único. Aqui temos um exemplo:
typeof(typeof 007); // retorna 'string'
No exemplo acima, a expressão typeof 007 é avaliada com o tipo number e retorna a string 'number'. typeof('number'), portanto, é o que resulta em uma 'string'.
Vamos ver outro exemplo para entender a importância dos parênteses com o operador typeof.
typeof(999-3223); // retorna "number"Se você omitir os parênteses, no entanto, ele retornará, NaN (Not a Number – em português, "não é um número"):
typeof 999-3223; // retorna NaNIsso ocorre porque, primeiramente, typeof 999 resultará na string "number". A expressão "number" - 32223 resultará em NaN, que é o que acontece quando você realiza uma operação de subtração entre uma string e um número.
Exemplos de uso de typeof em JavaScript
O trecho de código abaixo mostra o resultado da verificação de tipo para vários valores usando o operador typeof.
typeof 0; //'number'
typeof +0; //'number'
typeof -0; //'number'
typeof Math.sqrt(2); //'number'
typeof Infinity; //'number'
typeof NaN; //'number', mesmo que seja Not a Number
typeof Number('100'); //'number', depois da coerção de sucesso para número
typeof Number('freeCodeCamp'); //'number', apesar do fato de não poder fazer a coerção da string para um número
typeof true; //'boolean'
typeof false; //'boolean'
typeof Boolean(0); //'boolean'
typeof 12n; //'bigint'
typeof ''; //'string'
typeof 'freeCodeCamp'; //'string'
typeof `freeCodeCamp is awesome`; //'string'
typeof '100'; //'string'
typeof String(100); //'string'
typeof Symbol(); //'symbol'
typeof Symbol('freeCodeCamp'); //'symbol'
typeof {blog: 'freeCodeCamp', author: 'Tapas A'}; //'object';
typeof ['This', 'is', 101]; //'object'
typeof new Date(); //'object'
typeof Array(4); //'object'
typeof new Boolean(true); //'object';
typeof new Number(101); //'object';
typeof new String('freeCodeCamp'); //'object';
typeof new Object; //'object'
typeof alert; //'function'
typeof function () {}; //'function'
typeof (() => {}); //'function' – é uma arrow function. Assim, é necessário o parênteses
typeof Math.sqrt; //'function'
let a;
typeof a; //'undefined'
typeof b; //'undefined'
typeof undefined; //'undefined'
typeof null; //'object'A tabela abaixo mostra os valores de retorno da verificação de tipo com typeof:
| TIPO | VALOR DE RETORNO DE TYPEOF |
|---|---|
| String | 'string' |
| Number | 'number' |
| BigInt | 'bigint' |
| Symbol | 'symbol' |
| Boolean | 'boolean' |
| undefined | 'undefined' |
| Objeto function | 'function' |
| null | 'object'(ver abaixo!) |
| Qualquer outro objeto | 'object' |
Questões importantes com typeof
Há casos em que o operador typeof pode não retornar os tipos que se espera. Isso pode causar confusão e erros. Abaixo, veremos alguns desses casos:
O tipo de NaN é number
typeof NaN; //'number', mesmo que ele seja Not a Number (não é um número)typeof NaN retorna 'number'. Isso é estranho, já que não deveríamos detectar NaN usando typeof. Há maneiras melhores de se lidar com isso. Veremos essas maneiras em breve.
O tipo de null é object
typeof null; //'object'
Em JavaScript, typeof null retorna object, o que dá a impressão errada de que null é um objeto, embora ele seja um valor primitivo.
O resultado de typeof null é, na verdade, um bug na linguagem. Houve uma tentativa de consertá-lo no passado, mas foi rejeitada devido a um problema de compatibilidade com versões anteriores.
O tipo de uma variável não declarada é undefined
Antes da ES6, uma verificação de tipo de uma variável não declarada costumava resultar em 'undefined'. Esse, no entanto, não é um modo à prova de erros de se lidar com isso.
Com a chegada da ES6, podemos declarar variáveis com escopo de bloco com as palavras-chave let ou const. Se você as utilizar com o operador typeof antes de elas serem inicializadas, verá um ReferenceError (em português, "erro de referência").
typeof cat; // ReferenceError
let cat = 'brownie'; O tipo de uma função construtora é object
Todas as funções construtoras, com exceção do construtor de Function, sempre serão do tipo 'object'.
typeof new String('freeCodeCamp'); //'object'Isso pode causar uma certa confusão, já que esperamos que elas sejam do tipo de fato (no exemplo acima, do tipo string).
O tipo de um array é object
Embora isso esteja tecnicamente correto, pode desapontar bastante. Queremos diferenciar entre arrays e objetos, mesmo quando um array, tecnicamente, seja um objeto em JavaScript.
typeof Array(4); //'object'Felizmente, há maneiras de se detectar um array corretamente. Veremos isso em breve.
Para além de typeof – uma verificação de tipos melhor
Agora que vimos algumas das limitações do operador typeof, vejamos como consertá-las para termos uma verificação de tipos melhor.
Como detectar NaN
Em JavaScript, NaN é um valor especial. O valor NaN representa o resultado de uma expressão aritmética que não pode, de fato, ser representada. Por exemplo,
let result = 0/0;
console.log(result); // retorna NaN
Além disso, se realizarmos qualquer operação aritmética com NaN, o resultado sempre será NaN.
console.log(NaN + 3); // retorna NaN
A verificação de tipo de NaN usando o operador typeof não ajuda muito, pois ela retorna o tipo como 'number'. O JavaScript tem uma função global chamada isNaN() para detectar se um resultado é NaN.
isNaN(0/0); // retorna true
Porém, também temos um problema aqui.
isNaN(undefined); // retorna true para 'undefined'
Na ES6, o método isNaN() é adicionado ao objeto global Number. Esse método é muito mais confiável, sendo, portanto, o preferido.
Number.isNaN(0/0); // retorna true
Number.isNaN(undefined); // retorna false
Outro aspecto interessante de NaN é o fato de ser o único valor em JavaScript que nunca é igual a qualquer outro valor, incluindo ele mesmo. Então, há uma outra maneira de detectar NaN em ambientes onde não há suporte para a ES6:
function isNaN (input) {
return input !== input;
}
Como detectar null em JavaScript
Como vimos anteriormente, detectar null usando o operador typeof é confuso. A maneira preferida de se verificar se algo é null é usando o operador de igualdade estrita (===).
function isNull(input) {
return input === null;
}
Certifique-se de não usar == por engano. Se usar == no lugar de ===, você poderá ter como resultado uma detecção de tipo enganadora.
Como detectar um array em JavaScript
A partir da ES6, podemos detectar um array usando o método Array.isArray.
Array.isArray([]); // retorna true
Array.isArray({}); // retorna false
Antes da ES6, poderíamos usar o operador instanceof para determinar se algo era um array:
function isArray(input) {
return input instanceof Array;
}
Uma solução genérica para a verificação de tipos em JavaScript
Existe uma forma de criarmos uma solução genérica para a verificação de tipos. Dê uma olhada no método Object.prototype.toString. Ele é muito poderoso e extremamente útil para se escrever um método utilitário para a verificação de tipos.
Quando Object.prototype.toString é chamado usando call() ou apply(), ele retorna o tipo do objeto no formato [object Tipo Correspondente]. A parte do Tipo Correspondente no valor de retorno é o tipo verdadeiro.
Vamos ver como isso funciona com alguns exemplos:
// retorna '[object Array]'
Object.prototype.toString.call([]);
// retorna '[object Date]'
Object.prototype.toString.call(new Date());
// retorna '[object String]'
Object.prototype.toString.call(new String('freeCodeCamp'));
// retorna '[object Boolean]'
Object.prototype.toString.call(new Boolean(true));
// retorna '[object Null]'
Object.prototype.toString.call(null);
Isso quer dizer que, se simplesmente pegarmos a string de retorno e removermos a parte do object, teremos o tipo de fato. Aqui, vemos uma tentativa de se fazer isso:
function conferirTipo(valor) {
const valor_de_retorno = Object.prototype.toString.call(valor);
// também podemos usar uma regex para isso...
const tipo = valor_de_retorno.substring(
valor_de_retorno.indexOf(" ") + 1,
valor_de_retorno.indexOf("]"));
return tipo.toLowerCase();
}
Agora, podemos usar a função conferirTipo para detectar os tipos:
conferirTipo([]); // 'array'
conferirTipo(new Date()); // 'date'
conferirTipo(new String('freeCodeCamp')); // 'string'
conferirTipo(new Boolean(true)); // 'boolean'
conferirTipo(null); // 'null'
Em resumo
Para resumir o que aprendemos neste artigo:
- A verificação de tipos em JavaScript não é tão estrita como em outras linguagens de programação.
- Use o operador
typeofpara a detecção de tipos. - Existem duas sintaxes para o operador
typeof:typeofetypeof(expressão). - O resultado de um operador
typeofpode, por vezes, ser enganoso. Precisamos confiar em outros métodos disponíveis (Number.isNaN,Array.isArray, entre outros) nesses casos. - Podemos usar
Object.prototype.toStringpara criar um método de detecção de tipos genérico.
Antes de terminar...
Obrigado pela leitura até aqui! Conecte-se com o autor do texto pelo Twitter se quiser fazer comentários.
Você também pode gostar os seguintes artigos (em inglês):
- JavaScript undefined and null: Let's talk about it one last time!
- JavaScript: Equality comparison with ==, === and Object.is
- The JavaScript `this` Keyword + 5 Key Binding Rules Explained for JS Beginners
Por enquanto, é só. Até o próximo artigo. Cuide-se bem e bons estudos. 😉