»

»

Code Review TypeScript: Um Guia Prático e checklist
Índice:

Code Review TypeScript: Um Guia Prático e checklist

Índice:

Vamos ser sinceros: muito code review é só para cumprir tabela. Procuramos bugs óbvios, sugerimos renomear algumas variáveis e criticamos o estilo de código que o linter já deveria ter pego. Clicamos em “Approve”, ganhamos nossos pontos de bom colega de equipe e seguimos em frente. Mas um bom Code Review TypeScript é outra história. É menos sobre marcar caixinhas e mais sobre arquitetura colaborativa.

Ao revisar TypeScript, você não está apenas olhando para o código; você está olhando para a *forma* dos dados, os *contratos* entre componentes e a *história* que os tipos contam. Acerte, e você previne classes inteiras de bugs. Erre, e você está apenas escrevendo JavaScript com passos extras.

Isso não é sobre dogma. É sobre facilitar nossas vidas, construir coisas que não quebram de formas esquisitas e deixar a codebase melhor do que a encontramos.

Além do “Looks Good to Me”

Um ótimo review de TypeScript vai além da correção superficial. Ele atua como um multiplicador de força para a melhoria da qualidade do código.

Primeiro, é nossa melhor defesa contra bugs relacionados a tipos. Pense naquela vez em que uma função esperava uma `string`, mas recebeu um `number` em tempo de execução porque a resposta de uma API mudou. Uma definição de tipo adequada, talvez com uma biblioteca de validação como Zod, teria pego isso antes de chegar em produção.

Segundo, melhora drasticamente a legibilidade. Bons tipos são uma forma de documentação que nunca fica desatualizada. Quando você vê function processUser(user: User), sabe imediatamente que tipo de estrutura de dados esperar. Chega de ter que cavar em três arquivos para descobrir como é um objeto `user`.

Mas aqui está a parte com que devs sêniores realmente se importam: força um design de API melhor. Ao revisar um PR, você é o primeiro “cliente” daquela nova função, componente ou classe. Se você não consegue entender como usá-la apenas pela sua assinatura de tipo, a API é complicada demais. O review se torna uma sessão de design.

O que realmente procurar: A essência de um ótimo Code Review TypeScript

Ok, então onde você deve focar sua atenção? Tudo se resume a algumas áreas principais.

Segurança e Correção de Tipos

Este é o ponto de partida. Se os tipos estiverem errados, nada mais importa.

Esse texto está muito bom em conteúdo e opinião — direto, técnico e com ótimos exemplos. A estrutura também está clara. Abaixo está uma versão revisada apenas para deixar a escrita mais fluida, consistente e com um ritmo mais natural (especialmente nos títulos e pausas):

 A brecha do any

Minha opinião?
any é um code smell — não um pecado capital. Ele basicamente diz:

“Desisti da segurança de tipos aqui.”

Todo uso de any deve ser questionado:

  • É temporário?
  • Veio de uma lib sem tipos?
  • Dá pra usar unknown no lugar?

unknown é o primo mais seguro do any: obriga você a validar o tipo antes de usar a variável — o que quase sempre é o comportamento certo.

🚨 Abuso de type assertions

Ver as User ou <User> é um sinal de alerta.
É o equivalente a dizer pro TypeScript:

“Confia em mim, eu sei o que tô fazendo.”

Às vezes você realmente sabe — como em:

document.getElementById('app') as HTMLDivElement

Mas, na maioria dos casos, type assertions são usadas pra esconder uma incompatibilidade de tipos que deveria ser resolvida de verdade.

Use type guards no lugar:

function isUser(obj: unknown): obj is User

É mais robusto, mais explícito e muito mais seguro.

✅ Lidando com null e undefined

Se seu projeto ainda não usa "strictNullChecks": true no tsconfig.json, pare tudo e traga isso pro time.

Dói um pouco no começo — mas elimina erros como:
"Cannot read property 'x' of undefined".

Em code review, fique atento a código defensivo demais:

if (user && user.profile && user.profile.name)

Quando poderia ser simplesmente:

user?.profile?.name

Design de API e definição de tipos

Aqui é onde você coloca o chapéu de product designer.

Qual é a sensação de usar esse código?

Nome de tipos que contam uma história

ItemData é um nome preguiçoso.

Que tipo de item? ProductListItem? ShoppingCartItem?

Seja específico — bons nomes tornam o código autoexplicativo.

Em funções (especialmente em pacotes compartilhados de um monorepo), tipos de retorno explícitos são obrigatórios.
Não faça quem consome sua função adivinhar o que ela retorna.

Interfaces limpas e consistentes

Olhe pras props de um componente React. É só um monte de booleanos?

<Button isPrimary isDestructive isIconOnly />

Esse é um clássico sinal de que um union type cairia melhor:

<Button variant="primary" | "destructive" | "icon" />

Isso impede estados impossíveis. Você não quer permitir um botão que seja “primário” e “destrutivo” ao mesmo tempo.

Generics para reutilização

Se você vê funções parecidas que só mudam o tipo dos dados, isso é um ótimo candidato a generic.

Exemplo:

fetchUserData()
fetchProductData()

Podem virar:

fetchData<T>(url: string): Promise<T>

Em um review, identificar essas oportunidades é uma grande vitória para a manutenibilidade.

Tratamento de Erros

Erros vão acontecer. Como o sistema de tipos lida com isso?

O ponto principal aqui é: como capturar erros de forma segura.

Desde o TypeScript 4.4, o tipo padrão do catch virou unknown (antes era any). Isso é ótimo pra segurança — mas só se o time estiver usando direito.

Padrão problemático (ainda comum em configs antigas):

try {
// ...
} catch (err) {
console.error(err.message); // err é `any`
}

O ideal é sempre ser explícito e seguro:

try {
// ...
} catch (err: unknown) {
if (err instanceof Error) {
console.error(err.message);
} else {
console.error("An unknown error occurred");
}
}

Quem revisa deveria sugerir esse padrão sempre que ver um catch ambíguo.

Isso garante que você não tente acessar propriedades em algo que foi lançado no erro, que poderia ser uma string, um número ou um objeto nulo.

Como Conduzir o Processo de Review

O processo importa tanto quanto o conteúdo. Seguir boas práticas de code review faz toda a diferença.

Para o Autor: Prepare-se para o Sucesso

Não jogue seu código por cima do muro. Um pouco de preparação ajuda muito.

Faça um auto-review primeiro:

  • Rode tsc --noEmit — é sua primeira linha de defesa, pega erros de tipo sem precisar buildar o projeto.

  • Execute o linter e o formatador: eslint . --fix e prettier --write ..

  • Corrija o que for automático. Isso libera a pessoa que vai revisar pra focar no que realmente importa.

  • Se quiser uma ajuda extra, dá pra usar ferramentas de IA pra revisar o código também.

Escreva uma boa descrição para o PR: Explique o porquê, não apenas o o quê. Se você precisou criar um mapped type ou conditional type muito complexo, adicione um comentário explicando ou um link para o recurso específico do TypeScript que usou. Dê contexto!

Para o Revisor: Seja um Mentor, Não um Policial

Seu objetivo é melhorar o código — não provar que é mais inteligente.

Entenda a intenção: Leia a descrição do PR e o ticket associado. Que problema essa mudança resolve? Esse contexto evita sugestões que fogem do foco.

Priorize o feedback:
Use prefixos nos comentários. Algo simples já ajuda bastante:

  • [Blocker]: “Isso parece um bug ou um problema de arquitetura relevante. Precisamos resolver antes de fazer o merge.”

  • [Sugestão]: “Acho que daria pra deixar isso mais claro/eficiente fazendo X. O que acha?”

  • [Nitpick]: “É só uma questão de estilo — sinta-se à vontade para ignorar.”

Ofereça soluções: Não diga só “isso está confuso”. Diga: “Essa lógica condicional está difícil de seguir. Que tal extrair pra uma função chamada isEligibleForDiscount(cart)? Fica mais claro o que ela faz.”


O Checklist Definitivo de Code Review TypeScript

Aqui está um checklist prático e sem enrolação para usar no seu próximo PR. Pense nele como um guia, não um conjunto rígido de regras.

Perfeito. Aqui está a versão final organizada como um checklist enxuto e direto, pronta pra ser usada internamente ou compartilhada com o time:

✅ Tipagem e Correção

  • Está usando any? É justificável? unknown seria mais seguro?
  • Existem as Foo que poderiam ser evitados com um type guard ou tipagem melhor?
  • As funções exportadas têm tipo de retorno explícito?
  • Está usando generics quando a lógica é reutilizável?
  • null e undefined são tratados corretamente (?., ??)?
  • Está usando union types para representar estados ao invés de múltiplos booleanos?

✅ Organização e Manutenibilidade

  • Os nomes dos tipos são descritivos (Product > Data)?
  • Tipos estão no lugar certo (types.ts ou perto do código)?
  • Em monorepos, os tipos compartilhados estão bem exportados e limitados?
  • Tipos complexos têm nome próprio com type ou interface?

✅ Testes

  • Tipos complexos (conditional types) têm testes com tsd ou expect-type?
  • Mocks e dados de teste estão tipados corretamente e fiéis aos dados reais?

✅ Segurança

  • Inputs externos (API, usuário) são validados antes de confiar? Tipados como unknown no início?
  • Strings sensíveis (senha, token) têm tipo próprio pra evitar log acidental?
    type Password = string & { __brand: 'password' }
    

✅ Frontend (React)

  • Props estão bem definidas? Props opcionais usam ??
  • Event handlers estão corretamente tipados (nada de any)?
  • useState tem tipo correto (User | null, se aplicável)?
  • Custom hooks têm retorno bem tipado ([value, setValue] com tipo)?

✅ Backend (Node.js)

  • req.body e query estão validados e tipados (Zod, Joi)?
  • Os tipos refletem fielmente o schema do banco de dados?
  • Variáveis de ambiente são parseadas e tipadas na inicialização?

Ao ir além de um simples “LGTM” e se engajar com o código nesse nível, você está fazendo mais do que apenas revisar código. Você está moldando um produto mais estável, manutenível e amigável para pessoas desenvolvedoras. E é assim que se pode otimizar o processo de code review.

Publicado por:
Compartilhe:

Automatize seu Code Review com a Kody

Posts relacionados

Vamos ser sinceros: muito code review é só para cumprir tabela. Procuramos bugs óbvios, sugerimos renomear algumas variáveis e criticamos o estilo de código que o linter já deveria ter

Vamos ser sinceros: muito code review é só para cumprir tabela. Procuramos bugs óbvios, sugerimos renomear algumas variáveis e criticamos o estilo de código que o linter já deveria ter

Vamos ser sinceros: muito code review é só para cumprir tabela. Procuramos bugs óbvios, sugerimos renomear algumas variáveis e criticamos o estilo de código que o linter já deveria ter