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 NaN
Isso 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
typeof
para a detecção de tipos. - Existem duas sintaxes para o operador
typeof
:typeof
etypeof(expressão)
. - O resultado de um operador
typeof
pode, por vezes, ser enganoso. Precisamos confiar em outros métodos disponíveis (Number.isNaN
,Array.isArray
, entre outros) nesses casos. - Podemos usar
Object.prototype.toString
para 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. 😉