DEV Community

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 }
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
  }
}
Enter fullscreen mode Exit fullscreen mode

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;
};
Enter fullscreen mode Exit fullscreen mode

Correto:

type Carro = { tipo: 'carro'; portas: number };
type Moto = { tipo: 'moto'; cilindradas: number };
type Veiculo = Carro | Moto;
Enter fullscreen mode Exit fullscreen mode

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[]
Enter fullscreen mode Exit fullscreen mode

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' }]
Enter fullscreen mode Exit fullscreen mode

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> = [T] extends [Array<unknown>] ? T : T[];
type Resultado = ToList<string | number>; // Agora é (string | number)[]
Enter fullscreen mode Exit fullscreen mode

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');
  }
}
Enter fullscreen mode Exit fullscreen mode

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 };
Enter fullscreen mode Exit fullscreen mode

8. Use Tuplas ao Invés de Arrays Genéricos

type Coordenada = [number, number, string];
const minhaLocalizacao: Coordenada = [40.7128, -74.0060, 'Nova York'];
Enter fullscreen mode Exit fullscreen mode

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`
Enter fullscreen mode Exit fullscreen mode

**10. Evite Código Repetitivo com Manipulação de Tipos

Exemplo:

type Funcionario = { nome: string; cargo: string; salario: number };
type DadosSalariais = Pick<Funcionario, 'cargo' | 'salario'>;
Enter fullscreen mode Exit fullscreen mode

Isso elimina redundância ao criar novos tipos baseados em tipos existentes.

Playwright CLI Flags Tutorial

5 Playwright CLI Flags That Will Transform Your Testing Workflow

  • --last-failed: Zero in on just the tests that failed in your previous run
  • --only-changed: Test only the spec files you've modified in git
  • --repeat-each: Run tests multiple times to catch flaky behavior before it reaches production
  • --forbid-only: Prevent accidental test.only commits from breaking your CI pipeline
  • --ui --headed --workers 1: Debug visually with browser windows and sequential test execution

Learn how these powerful command-line options can save you time, strengthen your test suite, and streamline your Playwright testing experience. Practical examples included!

Watch Video 📹️

Top comments (0)

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

👋 Kindness is contagious

If you found this post useful, please drop a ❤️ or leave a kind comment!

Okay