Tipos básicos: string, number, boolean, any, unknown, never
1. Introdução aos tipos primitivos no TypeScript
O TypeScript estende o JavaScript adicionando um sistema de tipos estáticos. Isso significa que você pode declarar explicitamente que tipo de valor uma variável deve armazenar, e o compilador verificará se você está usando esse valor corretamente ao longo do código. Os tipos básicos — string, number, boolean, any, unknown e never — formam a fundação sobre a qual todos os outros tipos são construídos.
O TypeScript possui duas maneiras de lidar com tipos: inferência de tipos e anotação explícita. Na inferência, o TypeScript deduz automaticamente o tipo com base no valor atribuído. Na anotação explícita, você declara o tipo manualmente usando : após o nome da variável.
// Inferência: TypeScript deduz que nome é string
let nome = "Maria";
// Anotação explícita: declaramos que idade é number
let idade: number = 30;
Os benefícios são imediatos: segurança contra erros de tipo, intellisense aprimorado no editor e documentação viva que se mantém sincronizada com o código.
2. string, number e boolean: os pilares
string
O tipo string representa valores textuais. Você pode usar aspas simples, duplas ou template literals.
let saudacao: string = "Olá, mundo!";
let nome: string = 'João';
let mensagem: string = `Bem-vindo, ${nome}!`;
number
O tipo number cobre inteiros, floats, NaN e Infinity. O TypeScript também suporta BigInt para números muito grandes, mas é um tipo separado.
let inteiro: number = 42;
let decimal: number = 3.14;
let notANumber: number = NaN;
let infinito: number = Infinity;
// BigInt (tipo separado, não number)
let big: bigint = 9007199254740991n;
boolean
O tipo boolean aceita apenas true ou false.
let ativo: boolean = true;
let completo: boolean = false;
// Uso comum em condicionais
if (ativo) {
console.log("Usuário ativo");
}
Exemplos práticos combinando inferência e anotação:
// Inferência
let produto = "Notebook"; // TypeScript infere string
let preco = 2500.50; // infere number
let disponivel = true; // infere boolean
// Anotação explícita (útil quando a declaração está separada da atribuição)
let nomeCliente: string;
let idadeCliente: number;
let cadastroCompleto: boolean;
nomeCliente = "Ana";
idadeCliente = 28;
cadastroCompleto = true;
3. any: o tipo desligado
O tipo any é a "válvula de escape" do sistema de tipos. Quando você declara uma variável como any, o TypeScript desativa completamente a checagem de tipos para aquela variável.
let dado: any = "texto";
dado = 42; // OK
dado = true; // OK
dado.metodoInexistente(); // Sem erro de compilação, mas pode quebrar em runtime
Cenários de uso legítimos:
- Migração gradual de JavaScript para TypeScript
- Dados vindos de APIs externas sem tipagem definida
- Interação com bibliotecas JavaScript que não possuem tipos
Riscos: O any elimina a segurança que o TypeScript oferece. Use com moderação e prefira unknown quando possível.
// Exemplo de migração: código JS antigo sendo convertido
let dadosUsuario: any = fetchUserFromLegacyAPI();
4. unknown: o tipo seguro para dados desconhecidos
O tipo unknown é semanticamente similar ao any, mas com uma diferença crucial: você não pode operar com valores unknown sem primeiro fazer uma verificação de tipo (narrowing).
let valorDesconhecido: unknown = "Olá";
// Erro: não é possível acessar propriedades sem verificação
// console.log(valorDesconhecido.length); // Erro de compilação
// Narrowing obrigatório
if (typeof valorDesconhecido === "string") {
console.log(valorDesconhecido.length); // Agora OK
}
Exemplo prático: parsing de API externa
function processarRespostaAPI(resposta: unknown): string {
// Narrowing passo a passo
if (typeof resposta !== "object" || resposta === null) {
throw new Error("Resposta inválida");
}
// Precisamos de um tipo mais específico para acessar propriedades
if ("nome" in resposta && typeof (resposta as any).nome === "string") {
return (resposta as any).nome;
}
return "Desconhecido";
}
5. never: o tipo do impossível
O tipo never representa valores que nunca podem ocorrer. É usado principalmente em funções que nunca retornam (lançam exceção ou entram em loop infinito) e em verificações exaustivas de união de tipos.
// Função que nunca retorna (lança exceção)
function erro(mensagem: string): never {
throw new Error(mensagem);
}
// Função com loop infinito
function loopInfinito(): never {
while (true) {
// processamento contínuo
}
}
Uso em exhaustive checking com switch:
type Forma = "circulo" | "quadrado" | "triangulo";
function area(forma: Forma): number {
switch (forma) {
case "circulo":
return Math.PI * 5 * 5;
case "quadrado":
return 10 * 10;
case "triangulo":
return (10 * 8) / 2;
default:
// Se adicionarmos um novo tipo em Forma sem tratá-lo aqui,
// o TypeScript apontará erro
const _exaustivo: never = forma;
throw new Error(`Forma não tratada: ${forma}`);
}
}
6. Comparação prática: quando usar cada tipo
| Tipo | Quando usar | Evitar quando |
|---|---|---|
string/number/boolean |
Dados conhecidos e fixos | Dados de fontes externas não validadas |
unknown |
Dados externos (APIs, input do usuário) | Dados internos com tipo conhecido |
never |
Controle de fluxo, verificações exaustivas | Valores que realmente existem |
any |
Migração rápida, prototipação | Código de produção sem necessidade |
// Exemplo completo: processamento seguro de entrada
function processarEntrada(dado: unknown): string | number {
if (typeof dado === "string") {
return dado.toUpperCase();
}
if (typeof dado === "number") {
return dado * 2;
}
// Se chegar aqui, algo inesperado aconteceu
return erro("Tipo não suportado");
}
function erro(msg: string): never {
throw new Error(msg);
}
7. Erros comuns e boas práticas
Erro 1: Confundir null/undefined com never
function retornarNulo(): null {
return null; // Correto: null é um valor válido
}
// Incorreto: never não pode retornar valor algum
// function retornarNulo(): never {
// return null; // Erro de compilação
// }
Erro 2: Usar any por preguiça em vez de unknown
// Ruim: perde toda segurança de tipo
function processar(dado: any) {
return dado.nome.toUpperCase();
}
// Bom: força verificação de tipo
function processarSeguro(dado: unknown) {
if (typeof dado === "object" && dado !== null && "nome" in dado) {
return (dado as any).nome.toUpperCase();
}
throw new Error("Dado inválido");
}
Erro 3: Esquecer de fazer narrowing em unknown
function imprimir(dado: unknown) {
// Erro: não podemos chamar toString diretamente
// console.log(dado.toString());
// Correto: verificar antes
if (dado !== null && dado !== undefined) {
console.log(String(dado));
}
}
Dica importante: Ative strict: true no tsconfig.json para que o TypeScript pegue esses problemas automaticamente.
{
"compilerOptions": {
"strict": true
}
}
Com strict ativado, o TypeScript exige que você trate null e undefined adequadamente, além de forçar verificações mais rigorosas com unknown.
Referências
- TypeScript Handbook: Basic Types — Documentação oficial da Microsoft sobre tipos básicos, incluindo exemplos práticos de string, number, boolean, any, unknown e never.
- TypeScript Deep Dive: Type System — Guia abrangente sobre o sistema de tipos do TypeScript, com seções detalhadas sobre unknown e never.
- Understanding TypeScript’s unknown type — Artigo técnico explicando as diferenças entre any e unknown com exemplos reais de narrowing.
- TypeScript never type explained — Seção do handbook oficial focada no tipo never, incluindo uso em funções que nunca retornam e exhaustive checking.
- TypeScript Playground: Basic Types Examples — Ambiente interativo oficial para testar tipos básicos do TypeScript em tempo real.
- TypeScript Evolution: The unknown type — Artigo detalhado de Marius Schulz sobre a introdução do tipo unknown no TypeScript 3.0 e suas aplicações práticas.