Refatoração de código legado em TypeScript: do A ao Z
Trabalhar com código legado é uma realidade inevitável para muitos desenvolvedores. Frequentemente, esses projetos são escritos em JavaScript puro sem tipos, contêm dependências confusas e falta de testes. O TypeScript oferece um conjunto poderoso de ferramentas para melhorar gradualmente esse código, tornando-o mais seguro, legível e sustentável. Neste artigo, percorreremos o caminho desde a análise do código antigo até a criação de uma arquitetura limpa e tipificada.
1. Preparação e estratégia: por onde começar?
Antes de alterar o código, é necessário criar uma "rede de segurança". A regra principal da refatoração: não quebre o que funciona. Comece configurando o ambiente.
1.1. Inicialização do TypeScript e modo estrito
Instale o TypeScript e crie o arquivo de configuração tsconfig.json. No início, você pode desabilitar as verificações estritas para não se afogar em erros, mas gradualmente elas devem ser ativadas.
{ "compilerOptions": { "target": "ES2020", "module": "commonjs", "strict": true, // Comece com false, depois ative gradualmente "noImplicitAny": true, "strictNullChecks": true, "outDir": "./dist", "rootDir": "./src", "allowJs": true, // Permite misturar JS e TS "checkJs": false // Por enquanto, não verifica arquivos JS }, "include": ["src/**/*"]}1.2. Automação e testes
Adicione um linter (ESLint) e um formatador (Prettier). Se não houver testes, escreva pelo menos testes de integração para as partes críticas. Isso é seu seguro contra regressões.
- ESLint com plugin para TypeScript detectará erros lógicos.
- Jest ou Vitest para testes unitários.
- Configure hooks de pre-commit (Husky) para que o código seja verificado antes do commit.
2. Migração passo a passo: de JS para TS
Não tente reescrever tudo de uma vez. Use uma abordagem iterativa. A melhor ferramenta aqui é allowJs: true no tsconfig. Isso permite incluir arquivos JavaScript a partir do TypeScript.
2.1. Renomeação de arquivos e tipificação básica
Comece renomeando os arquivos mais simples, como utils.js ou helpers.js, para .ts. O compilador começará a reclamar de any implícitos. Sua tarefa é descrever as assinaturas das funções.
Antes (JavaScript):
function calculateDiscount(price, percent) { return price - (price * percent / 100);}Depois (TypeScript):
function calculateDiscount(price: number, percent: number): number { return price - (price * percent / 100);}2.2. Trabalhando com "any" e "unknown"
No código legado, há muitos any implícitos. Não tente tipificar tudo perfeitamente de imediato. Use any como solução temporária, mas marque com TODO. Para dados de fontes externas (API, localStorage), é melhor usar unknown com verificação de tipo posterior.
// Solução temporáriafunction processData(data: any) { // TODO: Adicionar tipo correto console.log(data.name);}
// Abordagem correta para dados externosfunction processUserData(data: unknown) { if (typeof data === 'object' && data !== null && 'id' in data) { const user = data as { id: number; name: string }; console.log(user.name); }}3. Refatoração de construções complexas
Quando a tipificação básica estiver pronta, passe para a melhoria da arquitetura. O código legado frequentemente sofre de "objetos divinos" e cadeias de chamadas confusas.
3.1. Criação de interfaces e tipos
Em vez de passar objetos com estrutura desconhecida, crie interfaces. Isso torna o código autodocumentável.
// Ruimfunction saveUser(user: any) { // Não está claro quais campos user possui}
// Bo