Refatoração de código legado em TypeScript: guia passo a passo

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course
Here is the translated HTML content in Portuguese (Português), with all HTML tags preserved and only the text content translated. ```html

Introdução: por que a refatoração de código legado para TypeScript é uma necessidade

Trabalhar com código legado é uma das tarefas mais frequentes e desafiadoras para um desenvolvedor. Frequentemente, esse código é escrito em JavaScript puro, sem tipagem estrita, contém dependências confusas e falta de estrutura modular. A migração para TypeScript não apenas adiciona tipos — é uma melhoria fundamental na qualidade do código, que reduz o número de bugs, simplifica a refatoração e acelera a integração de novos desenvolvedores.

Neste artigo, vamos detalhar o processo passo a passo de refatoração de código legado para TypeScript. Você aprenderá como introduzir tipos com segurança, dividir funções monolíticas e testar as alterações.



Passo 1. Análise e preparação do código legado

Antes de escrever código, é necessário entender a arquitetura atual. Sem isso, a refatoração se tornará um caos.



Crie um mapa de dependências

Comece analisando arquivos e módulos. Identifique:

  • Quais funções são "puras" (pure) e quais têm efeitos colaterais.
  • Onde estão as variáveis globais e estados.
  • Quais partes do código estão duplicadas.


Escreva testes para as partes críticas

Refatoração sem testes é jogar roleta-russa. Escreva pelo menos testes unitários para as funções-chave. Exemplo de teste em TypeScript:

// Código legado original (JavaScript)function calculatePrice(items) {    let total = 0;    for (let i = 0; i < items.length; i++) {        total += items[i].price * items[i].quantity;    }    return total;}

// Teste em TypeScript (Jest)describe('calculatePrice', () => { it('should calculate total price correctly', () => { const items = [ { price: 10, quantity: 2 }, { price: 5, quantity: 3 } ]; expect(calculatePrice(items)).toBe(35); });});


Se os testes passarem — você pode começar a refatoração.



Passo 2. Introdução gradual de tipagem estrita

Não tente cobrir tudo com tipos de uma vez. Use a estratégia "de baixo para cima": comece pelas funções mais simples e isoladas.



Tipagem de funções simples

Adicione tipos para parâmetros e valores de retorno. Exemplo:

// Antes (JavaScript)function greet(name) {    return "Hello, " + name;}

// Depois (TypeScript)function greet(name: string): string { return `Hello, ${name}`;}


Trabalhando com objetos e interfaces

Para estruturas de dados complexas, crie interfaces. Isso torna o código autodocumentado:

// Definindo a interface para um item de pedidointerface OrderItem {    id: number;    name: string;    price: number;    quantity: number;}

// Função com parâmetro tipadofunction getTotalPrice(items: OrderItem[]): number { return items.reduce((sum, item) => sum + item.price * item.quantity, 0);}


Use `any` apenas como solução temporária

O tipo any é inimigo da tipagem estrita. Se você não sabe o tipo exato, use unknown e verifique-o em tempo de execução:

function safeParse(data: unknown): string {    if (typeof data === 'string') {        return data.trim();    }    return '';}


Passo 3. Separação de funções e módulos monolíticos

Código legado frequentemente contém "funções divinas" (god functions) que fazem tudo de uma vez. Divida-as em módulos pequenos e reutilizáveis.



Isolando a lógica pura

Exemplo: uma função que valida email e envia uma requisição. Vamos separá-la:

// Antes (monolítico)function processUser(email) {    if (!email || !email.includes('@')) {        throw new Error('Invalid email');    }    // ... envio da requisição    console.log('Sending request...');}

// Depois (separação de responsabilidades)function validateEmail(email: string): boolean { return email ```

Blogs

Book Recommendations