CodeForge

TypeScript de Cero a Experto / Configuración pro

paths: adiós a los imports con laberintos de puntos

Teoría18 min20 XP

import { Boton } from "../../../componentes/ui/Boton" es feo, frágil y se rompe cuando mueves un archivo. Los paths de TypeScript te dejan escribir import { Boton } from "@/componentes/ui/Boton" —un alias limpio desde la raíz—. Es una mejora de calidad de vida que verás en todo proyecto profesional, y se configura en dos líneas.

Direcciones absolutas en vez de "a tres cuadras a la izquierda"

Configurar paths

Se definen en tsconfig.json con baseUrl (el punto de partida) y paths (los alias):

tsconfig.json
{
"compilerOptions": {
  "baseUrl": ".",              // la raíz desde donde se resuelven los paths
  "paths": {
    "@/*": ["./src/*"]         // @/ apunta a ./src/
  }
}
}

El resultado transforma tus imports de laberintos a direcciones limpias:

imports.ts
// ❌ antes: frágil y difícil de leer, se rompe al mover el archivo
import { Boton } from "../../../componentes/ui/Boton";
import { formatearPeso } from "../../../lib/dinero";
import { useGastos } from "../../hooks/useGastos";

// ✅ después: limpio, estable, apunta siempre al mismo lugar
import { Boton } from "@/componentes/ui/Boton";
import { formatearPeso } from "@/lib/dinero";
import { useGastos } from "@/hooks/useGastos";

"@/*": ["./src/*"] dice "cualquier import que empiece con @/ búscalo en ./src/". Así @/lib/dinero resuelve a ./src/lib/dinero, desde cualquier archivo del proyecto. Puedes definir varios alias (@/componentes, @/lib, @ui…), pero el patrón @/*src/* cubre casi todo y es el estándar de Next.js y compañía.

moduleResolution: cómo TS encuentra los módulos

Un ajuste relacionado que define la ESTRATEGIA con la que TS busca los archivos de un import:

module-resolution.ts
{
"compilerOptions": {
  // "bundler": la estrategia moderna, para proyectos con Vite/Next/esbuild.
  // Entiende package.json "exports", extensiones opcionales, etc.
  "moduleResolution": "bundler",

  // otras opciones históricas: "node16"/"nodenext" (para Node con ESM),
  // "node10" (la vieja de CommonJS). "bundler" es la recomendada hoy
  // para apps de frontend con un bundler.
}
}

moduleResolution: "bundler" es la opción moderna para apps con un empaquetador: entiende cómo los bundlers resuelven los imports (los exports del package.json, las extensiones). Para código de Node puro con ESM, usarías "nodenext". Rara vez lo tocas a mano —los tsconfig que generan los frameworks ya lo ponen bien—, pero saber que existe te ayuda cuando un import "no se encuentra" y la causa es la estrategia de resolución.

Configuras 'paths': { '@/*': ['./src/*'] } en tsconfig y los imports @/ funcionan en tu editor, pero al ejecutar con node (sin bundler) fallan con 'Cannot find module @/lib/x'. ¿Por qué?

Mini-reto

Limpia tus imports (en un proyecto con bundler): 1) agrega baseUrl: "." y paths: { "@/*": ["./src/*"] } al tsconfig; 2) cambia un import relativo largo (../../lib/algo) por su versión con alias (@/lib/algo) y confirma que el editor lo resuelve y autocompleta; 3) mueve el archivo que hace el import a otra carpeta y observa que el import con alias NO se rompe (mientras que uno relativo sí lo haría). Sientes por qué los alias son estándar.

Qué sigue

Tu proyecto individual está afinado. La próxima lección mira más allá: cuando tu código crece a VARIOS proyectos que dependen entre sí (un monorepo), los project references de TypeScript los orquestan para compilar rápido y con límites claros. La configuración a escala.