Cómo los alias en TypeScript ahorran horas de tu vida
\n¿Alguna vez has escrito algo como import UserService from '../../../../../services/UserService'? Si es así, conoces ese dolor. Los ojos se pierden, la refactorización se convierte en una pesadilla y cualquier movimiento de archivo rompe toda la cadena de importaciones. Afortunadamente, TypeScript (y su archivo de configuración tsconfig.json) ofrece una solución elegante: paths.
Pero la pregunta es: ¿cómo funciona esto bajo el capó? ¿Por qué, al definir el alias "@/*", puedes escribir import { UserService } from '@/services/UserService'? Y lo más importante, ¿por qué a veces no funciona sin configuraciones adicionales del empaquetador (webpack, Vite, Rollup)?
En este artículo no solo mostraremos cómo configurar paths en tsconfig.json. Nos adentraremos en el mecanismo interno, entenderemos el path mapping, aprenderemos cómo TypeScript resuelve los módulos y evitaremos errores típicos.
\n\n¿Qué son los paths en tsconfig.json?
\nPaths es una sección en tsconfig.json que permite definir asignaciones (mapping) personalizadas entre alias de importación y rutas reales a archivos. En pocas palabras, le dices a TypeScript: «Cuando encuentres una importación que comience con @utils/, en realidad busca el archivo en la carpeta src/utils/».
Así es como se ve en el código:
\n\n// tsconfig.json\n{\n "compilerOptions": {\n "baseUrl": ".",\n "paths": {\n "@/*": ["src/*"],\n "@utils/*": ["src/utils/*"],\n "@components/*": ["src/components/*"]\n }\n }\n}\n\n\nAhora, en lugar de horribles rutas relativas, escribes:
\n// Antes (pesadilla)\nimport { formatDate } from '../../../../utils/dateHelpers';\n\n// Ahora (belleza)\nimport { formatDate } from '@utils/dateHelpers';\n\n\n¿Estás de acuerdo? La diferencia es enorme. Pero, ¿cómo sabe TypeScript a dónde ir?
\n\nCómo funciona la resolución de módulos bajo el capó
\nPara entender el path mapping en TypeScript, es necesario comprender el mecanismo básico de resolution (resolución de módulos). Cuando TypeScript compila tu código, utiliza una estrategia similar a la de Node.js, pero con capacidades adicionales.
\nEl proceso es el siguiente:
\n- \n
- Verificación de ruta absoluta (comienza con
/) — si es así, busca desde la raíz del sistema de archivos. \n - Verificación de ruta relativa (comienza con
./o../) — resuelve en relación al archivo actual. \n - Verificación de alias de paths — si la importación comienza con un prefijo definido en
paths, TypeScript lo reemplaza con la ruta correspondiente del mapeo. \n - Búsqueda en node_modules — si nada coincide, busca el módulo como un paquete npm. \n
Punto clave: TypeScript no modifica las rutas físicas en el JavaScript compilado. Simplemente verifica los tipos y muestra errores si no encuentra el archivo. La sustitución de alias por rutas reales en tiempo de ejecución es tarea del empaquetador (webpack, Vite, tsc-alias).
\n\n¿Por qué los paths no funcionan «de fábrica»?
\nEsta es la pregunta más frecuente en Stack Overflow: «Configuré los paths, pero al ejecutar la aplicación aparece el error "Cannot find module"». La razón es simple: TypeScript es un transpilador, no un empaquetador.
\nCuando ejecutas tsc, genera archivos JS, pero deja los alias intactos. Por ejemplo, import { foo } from '@utils/bar' permanecerá en JS tal cual. Node.js (o el navegador) no tiene idea de qué es @utils y muestra un error.
Para solucionarlo, debes usar una de las siguientes soluciones:
\n- \n
- tsc-alias — una utilidad que, después de la compilación, reemplaza los alias por rutas reales. \n
- module-alias — un paquete npm para registrar alias en N \n