10 Dicas para se Tornar um Melhor Programador TypeScript
TypeScript vai muito além de simples anotações de tipo no JavaScript. Seu verdadeiro potencial está na composição de tipos, inferência automática e manipulação avançada, permitindo que você escreva código mais seguro, legível e eficiente. Neste artigo, exploramos práticas recomendadas que podem elevar suas habilidades e tornar seu código TypeScript mais poderoso. 1. Pense em "Conjuntos" ao Trabalhar com Tipos Cada tipo em TypeScript pode ser visto como um conjunto de valores. Isso ajuda a entender operações como união (|) e interseção (&). *Exemplo: * type Dimensao = { altura: number; largura: number }; type Aparencia = { cor: string; opacidade: number }; type Janela = Dimensao & Aparencia; // { altura: number; largura: number; cor: string; opacidade: number } Aqui, & cria uma interseção, garantindo que Janela tenha todas as propriedades. Comparação: & Interseção: elementos comuns aos dois tipos `` União: elementos de ambos os tipos 2. Diferencie "Tipo Declarado" e "Tipo Reduzido" TypeScript ajusta automaticamente os tipos com base no fluxo do código. Exemplo: function processar(valor: string | boolean) { if (typeof valor === 'string') { console.log(valor.toUpperCase()); // OK, pois TypeScript reduz valor para string } } Isso evita a necessidade de conversões desnecessárias. 3. Prefira União Discriminada a Campos Opcionais Usar type com uma propriedade discriminatória melhora a segurança do código. Errado: type Veiculo = { tipo: 'carro' | 'moto'; portas?: number; cilindradas?: number; }; Correto: type Carro = { tipo: 'carro'; portas: number }; type Moto = { tipo: 'moto'; cilindradas: number }; type Veiculo = Carro | Moto; 4. Use "Type Predicate" para Evitar "Type Assertion" Usar um type predicate permite que o TypeScript compreenda automaticamente a especialização de tipos dentro de funções, evitando a necessidade de conversões explícitas (as). Isso melhora a segurança do código e reduz erros inesperados. Exemplo: function isCarro(veiculo: Veiculo): veiculo is Carro { return veiculo.tipo === 'carro'; } const veiculos: Veiculo[] = obterVeiculos(); const carros = veiculos.filter(isCarro); // TypeScript agora sabe que isso é um Carro[] Outro Exemplo: type Animal = { tipo: 'cachorro' | 'gato'; som?: string }; type Cachorro = { tipo: 'cachorro'; som: 'latido' }; type Gato = { tipo: 'gato'; som: 'miado' }; type Especie = Cachorro | Gato; function isCachorro(animal: Especie): animal is Cachorro { return animal.tipo === 'cachorro'; } const animais: Especie[] = [ { tipo: 'cachorro', som: 'latido' }, { tipo: 'gato', som: 'miado' } ]; const apenasCachorros = animais.filter(isCachorro); console.log(apenasCachorros); // [{ tipo: 'cachorro', som: 'latido' }] 5. Controle como Tipos de União São Distribuídos TypeScript distribui tipos em uniões automaticamente. Podemos alterar isso com colchetes: Exemplo: type ToList = [T] extends [Array] ? T : T[]; type Resultado = ToList; // Agora é (string | number)[] 6. Utilize "Exaustividade" em switch para Evitar Casos Não Tratados Usar never pode ajudar a garantir que todas as possibilidades sejam cobertas: function calcularDesconto(produto: Produto) { switch (produto.categoria) { case 'eletronico': return produto.preco * 0.9; case 'vestuario': return produto.preco * 0.8; default: const exaustivo: never = produto; throw new Error('Categoria desconhecida'); } } 7. Prefira type a interface Use type, a menos que precise de declaration merging ou de OO: type Cliente = { nome: string; idade: number; email: string }; 8. Use Tuplas ao Invés de Arrays Genéricos type Coordenada = [number, number, string]; const minhaLocalizacao: Coordenada = [40.7128, -74.0060, 'Nova York']; 9. Controle a Especificidade da Inferência de Tipos Use as const para restringir valores. Use satisfies para validar sem alterar inferência: const produto = { preco: 100, nome: 'Notebook' } satisfies { preco: number; nome?: string }; console.log(produto.nome.length); // Ok, pois TypeScript sabe que nome não é `undefined` **10. Evite Código Repetitivo com Manipulação de Tipos Exemplo: type Funcionario = { nome: string; cargo: string; salario: number }; type DadosSalariais = Pick; Isso elimina redundância ao criar novos tipos baseados em tipos existentes.

TypeScript vai muito além de simples anotações de tipo no JavaScript. Seu verdadeiro potencial está na composição de tipos, inferência automática e manipulação avançada, permitindo que você escreva código mais seguro, legível e eficiente. Neste artigo, exploramos práticas recomendadas que podem elevar suas habilidades e tornar seu código TypeScript mais poderoso.
1. Pense em "Conjuntos" ao Trabalhar com Tipos
Cada tipo em TypeScript pode ser visto como um conjunto de valores. Isso ajuda a entender operações como união (|) e interseção (&).
*Exemplo: *
type Dimensao = { altura: number; largura: number };
type Aparencia = { cor: string; opacidade: number };
type Janela = Dimensao & Aparencia; // { altura: number; largura: number; cor: string; opacidade: number }
Aqui, & cria uma interseção, garantindo que Janela tenha todas as propriedades.
Comparação:
& Interseção: elementos comuns aos dois tipos
`` União: elementos de ambos os tipos
2. Diferencie "Tipo Declarado" e "Tipo Reduzido"
TypeScript ajusta automaticamente os tipos com base no fluxo do código.
Exemplo:
function processar(valor: string | boolean) {
if (typeof valor === 'string') {
console.log(valor.toUpperCase()); // OK, pois TypeScript reduz valor para string
}
}
Isso evita a necessidade de conversões desnecessárias.
3. Prefira União Discriminada a Campos Opcionais
Usar type com uma propriedade discriminatória melhora a segurança do código.
Errado:
type Veiculo = {
tipo: 'carro' | 'moto';
portas?: number;
cilindradas?: number;
};
Correto:
type Carro = { tipo: 'carro'; portas: number };
type Moto = { tipo: 'moto'; cilindradas: number };
type Veiculo = Carro | Moto;
4. Use "Type Predicate" para Evitar "Type Assertion"
Usar um type predicate permite que o TypeScript compreenda automaticamente a especialização de tipos dentro de funções, evitando a necessidade de conversões explícitas (as). Isso melhora a segurança do código e reduz erros inesperados.
Exemplo:
function isCarro(veiculo: Veiculo): veiculo is Carro {
return veiculo.tipo === 'carro';
}
const veiculos: Veiculo[] = obterVeiculos();
const carros = veiculos.filter(isCarro); // TypeScript agora sabe que isso é um Carro[]
Outro Exemplo:
type Animal = { tipo: 'cachorro' | 'gato'; som?: string };
type Cachorro = { tipo: 'cachorro'; som: 'latido' };
type Gato = { tipo: 'gato'; som: 'miado' };
type Especie = Cachorro | Gato;
function isCachorro(animal: Especie): animal is Cachorro {
return animal.tipo === 'cachorro';
}
const animais: Especie[] = [
{ tipo: 'cachorro', som: 'latido' },
{ tipo: 'gato', som: 'miado' }
];
const apenasCachorros = animais.filter(isCachorro);
console.log(apenasCachorros); // [{ tipo: 'cachorro', som: 'latido' }]
5. Controle como Tipos de União São Distribuídos
TypeScript distribui tipos em uniões automaticamente. Podemos alterar isso com colchetes:
Exemplo:
type ToList = [T] extends [Array] ? T : T[];
type Resultado = ToList; // Agora é (string | number)[]
6. Utilize "Exaustividade" em switch para Evitar Casos Não Tratados
Usar never pode ajudar a garantir que todas as possibilidades sejam cobertas:
function calcularDesconto(produto: Produto) {
switch (produto.categoria) {
case 'eletronico':
return produto.preco * 0.9;
case 'vestuario':
return produto.preco * 0.8;
default:
const exaustivo: never = produto;
throw new Error('Categoria desconhecida');
}
}
7. Prefira type a interface
Use type, a menos que precise de declaration merging ou de OO:
type Cliente = { nome: string; idade: number; email: string };
8. Use Tuplas ao Invés de Arrays Genéricos
type Coordenada = [number, number, string];
const minhaLocalizacao: Coordenada = [40.7128, -74.0060, 'Nova York'];
9. Controle a Especificidade da Inferência de Tipos
Use as const para restringir valores.
Use satisfies para validar sem alterar inferência:
const produto = { preco: 100, nome: 'Notebook' } satisfies { preco: number; nome?: string };
console.log(produto.nome.length); // Ok, pois TypeScript sabe que nome não é `undefined`
**10. Evite Código Repetitivo com Manipulação de Tipos
Exemplo:
type Funcionario = { nome: string; cargo: string; salario: number };
type DadosSalariais = Pick;
Isso elimina redundância ao criar novos tipos baseados em tipos existentes.