Refactorización de código legacy a TypeScript: de la A a la Z
Trabajar con código heredado (legacy) es una realidad inevitable para muchos desarrolladores. A menudo, estos proyectos están escritos en JavaScript "puro" sin tipos, contienen dependencias enredadas y carecen de pruebas. TypeScript ofrece un potente conjunto de herramientas para mejorar gradualmente dicho código, haciéndolo más seguro, legible y mantenible. En este artículo, recorreremos el camino desde el análisis del código antiguo hasta la creación de una arquitectura limpia y tipificada.
1. Preparación y estrategia: ¿por dónde empezar?
Antes de modificar el código, es necesario crear una "red de seguridad". La regla principal de la refactorización: no rompas lo que funciona. Comience configurando el entorno.
1.1. Inicialización de TypeScript y modo estricto
Instale TypeScript y cree un archivo de configuración tsconfig.json. Al principio, puede desactivar las comprobaciones estrictas para no ahogarse en errores, pero gradualmente debe activarlas.
{ "compilerOptions": { "target": "ES2020", "module": "commonjs", "strict": true, // Comience con false, luego actívelo gradualmente "noImplicitAny": true, "strictNullChecks": true, "outDir": "./dist", "rootDir": "./src", "allowJs": true, // Permitir mezclar JS y TS "checkJs": false // Por ahora, no revisar archivos JS }, "include": ["src/**/*"]}1.2. Automatización y pruebas
Agregue un linter (ESLint) y un formateador (Prettier). Si no hay pruebas, escriba al menos pruebas de integración para las partes críticas. Esto es su seguro contra regresiones.
- ESLint con el plugin para TypeScript detectará errores lógicos.
- Jest o Vitest para pruebas unitarias.
- Configure hooks de pre-commit (Husky) para que el código sea revisado antes de cada commit.
2. Migración paso a paso: de JS a TS
No intente reescribir todo de una vez. Utilice un enfoque iterativo. La mejor herramienta aquí es allowJs: true en tsconfig. Esto permite incluir archivos JavaScript desde TypeScript.
2.1. Renombrar archivos y tipificación básica
Comience renombrando los archivos más simples como utils.js o helpers.js a .ts. El compilador comenzará a quejarse de los any implícitos. Su tarea es describir las firmas de las funciones.
Antes (JavaScript):
function calculateDiscount(price, percent) { return price - (price * percent / 100);}Después (TypeScript):
function calculateDiscount(price: number, percent: number): number { return price - (price * percent / 100);}2.2. Trabajar con "any" y "unknown"
En el código legacy hay muchos any implícitos. No intente tipificarlo todo perfectamente de inmediato. Use any como solución temporal, pero márquelo con un TODO. Para datos de fuentes externas (API, localStorage), es mejor usar unknown con una verificación de tipo posterior.
// Solución temporalfunction processData(data: any) { // TODO: Agregar el tipo correcto console.log(data.name);}
// Enfoque correcto para datos 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. Refactorización de construcciones complejas
Una vez que la tipificación básica esté lista, pase a mejorar la arquitectura. El código legacy a menudo sufre de "objetos divinos" y cadenas de llamadas enredadas.
3.1. Extracción de interfaces y tipos
En lugar de pasar objetos con una estructura desconocida, cree interfaces. Esto hace que el código sea autodocumentado.
// Malofunction saveUser(user: any) { // No está claro qué campos tiene user}
// Bue