En esta página
Configuración y tsconfig.json
Configuración y tsconfig.json
Antes de escribir una sola línea de TypeScript en un proyecto real, necesitas configurar el compilador correctamente. Un tsconfig.json mal configurado puede dejarte con un TypeScript que no te protege de casi nada, o peor aún, con un proyecto que compila pero genera JavaScript incompatible con tu entorno de destino. Esta lección te da el conocimiento para configurar TypeScript correctamente desde el primer día.
Instalación
TypeScript se instala como dependencia de desarrollo. En la mayoría de los proyectos no necesitas TypeScript en producción, ya que el código se compila antes del despliegue.
# Con npm
npm install --save-dev typescript
# Con bun (más rápido)
bun add -d typescript
# Verificar la versión instalada
npx tsc --version
# Version 6.0.0Para inicializar un tsconfig.json con valores por defecto razonables:
npx tsc --initEsto genera un archivo con todas las opciones posibles, la mayoría comentadas. Te recomiendo empezar desde cero con solo las opciones que necesitas, que es lo que haremos en esta lección.
La estructura del tsconfig.json
El archivo tsconfig.json tiene tres secciones principales:
{
"compilerOptions": { },
"include": [],
"exclude": []
}compilerOptions: controla el comportamiento del compilador.include: qué archivos TypeScript debe procesar.exclude: qué archivos o directorios ignorar.
También existe extends para heredar configuración de otro archivo, y references para proyectos compuestos (monorepos).
compilerOptions: las opciones esenciales
`target`: el JavaScript de destino
"target": "ES2022"Define a qué versión de JavaScript se compila el código. Si tu entorno es Node.js 18+, usa ES2022. Si necesitas soportar navegadores sin bundler, ajusta según el soporte requerido. Los valores comunes son ES5, ES6/ES2015, ES2020, ES2022, y ESNext.
Con target: "ES2022" TypeScript puede emitir clases nativas, async/await nativo, métodos de array modernos como .at(), y operadores de asignación lógica (??=, &&=, ||=).
`module`: el sistema de módulos
"module": "NodeNext"Controla cómo se emiten las importaciones y exportaciones. Las opciones más relevantes en 2025 son:
NodeNext: Para Node.js con ESM o CJS. TypeScript lee el campotypede tupackage.jsonpara determinar el formato.ESNext: Para bundlers modernos (Vite, webpack, esbuild) que manejan la resolución ellos mismos.CommonJS: Para Node.js legacy.
`moduleResolution`: cómo se resuelven los imports
"moduleResolution": "NodeNext"Debe estar sincronizado con module. Si usas module: "NodeNext", usa moduleResolution: "NodeNext". Para bundlers, "Bundler" es la opción correcta en TypeScript 5+.
Con NodeNext, TypeScript requiere extensiones explícitas en los imports relativos:
// ✅ Correcto con NodeNext
import { calcular } from './utils.js'; // Nota: .js aunque el archivo sea .ts
// ❌ Incorrecto con NodeNext
import { calcular } from './utils';`strict`: el escudo completo
"strict": trueEsta es la opción más importante. Activa un conjunto de verificaciones que hacen TypeScript realmente útil:
strictNullChecks:nullyundefinedson tipos separados. Sin esto, puedes asignarnulla cualquier variable sin que TypeScript se queje.noImplicitAny: Obliga a declarar tipos cuando TypeScript no puede inferirlos. Sin esto, TypeScript aceptaanyimplícito silenciosamente.strictFunctionTypes: Verifica la covarianza/contravarianza en tipos de funciones.useUnknownInCatchVariables: En bloquescatch, la variable de error esunknownen lugar deany.
Opciones adicionales que deberías activar
"noUncheckedIndexedAccess": trueAl acceder a un arreglo por índice (arr[0]), el tipo resultante incluye undefined. Esto fuerza a verificar que el elemento existe antes de usarlo, eliminando un tipo muy común de bug en tiempo de ejecución.
const nombres = ['Ana', 'Carlos', 'María'];
const primero = nombres[0]; // tipo: string | undefined (con noUncheckedIndexedAccess)
console.log(primero.toUpperCase()); // ❌ Error: 'primero' is possibly 'undefined'
console.log(primero?.toUpperCase()); // ✅ 'ANA'"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"noUnusedLocals": true,
"noUnusedParameters": trueEstas opciones detectan código muerto y rutas de retorno faltantes.
`outDir` y `rootDir`: organización de archivos
"outDir": "./dist",
"rootDir": "./src"rootDir indica dónde están los archivos fuente TypeScript. outDir indica dónde se generan los archivos JavaScript compilados. Esta separación mantiene el repositorio limpio.
`esModuleInterop`: compatibilidad con módulos CommonJS
"esModuleInterop": truePermite importar módulos CommonJS (como la mayoría de los paquetes npm) con sintaxis de import por defecto:
// Sin esModuleInterop:
import * as fs from 'fs';
// Con esModuleInterop:
import fs from 'fs';`paths`: alias de importación
"paths": {
"@utils/*": ["./src/utils/*"],
"@models/*": ["./src/models/*"]
}Los alias permiten importar con rutas cortas en lugar de rutas relativas largas:
// Sin alias: relativo y frágil
import { formatearFecha } from '../../../utils/fecha';
// Con alias: limpio y robusto
import { formatearFecha } from '@utils/fecha';Importante: paths solo afecta a TypeScript. Si usas un bundler, también debes configurar los alias ahí (Vite: resolve.alias, webpack: resolve.alias).
`declaration` y `sourceMap`: para librerías
"declaration": true,
"declarationMap": true,
"sourceMap": truedeclaration: true genera archivos .d.ts con las definiciones de tipos, necesario si publicas una librería npm. sourceMap: true genera mapas de fuente para depuración, conectando el JavaScript compilado con el TypeScript original.
Ejecutar el compilador
# Compilar una vez
npx tsc
# Compilar en modo watch (recompila al guardar)
npx tsc --watch
# Verificar tipos sin emitir archivos
npx tsc --noEmit
# Compilar un archivo específico (ignora tsconfig.json)
npx tsc archivo.ts --target ES2022El modo --noEmit es especialmente útil en CI/CD para verificar que el código compila correctamente sin generar archivos.
TypeScript en Node.js: tsx vs ts-node
Para ejecutar archivos TypeScript directamente sin compilar, tienes varias opciones:
tsx (recomendado): usa esbuild internamente, es muy rápido y soporta import.meta.
npx tsx src/index.ts
# O instalar globalmente:
npm install -g tsx
tsx src/index.tsts-node: la opción clásica, más lenta pero con más opciones de configuración.
npm install -D ts-node
npx ts-node src/index.tsBun: ejecuta TypeScript nativamente, sin configuración adicional.
bun run src/index.tsPara scripts de desarrollo, seeds de base de datos y herramientas internas, tsx es la elección pragmática: sin pasos de compilación, sin archivos generados.
Estructura recomendada para un proyecto Node.js
mi-proyecto/
├── src/
│ ├── index.ts
│ ├── models/
│ └── utils/
├── dist/ (generado por tsc, añadir a .gitignore)
├── tsconfig.json
├── package.json
└── .gitignoreEl package.json típico:
{
"name": "mi-proyecto",
"type": "module",
"scripts": {
"build": "tsc",
"dev": "tsx watch src/index.ts",
"typecheck": "tsc --noEmit",
"start": "node dist/index.js"
}
}Con esta configuración tienes un flujo de desarrollo fluido: npm run dev para desarrollo con recarga automática, npm run typecheck para verificar tipos en CI, y npm run build para producción.
Herencia de configuración con `extends`
Para proyectos con múltiples entornos (producción, pruebas, desarrollo), puedes usar extends:
// tsconfig.base.json
{
"compilerOptions": {
"target": "ES2022",
"strict": true,
"esModuleInterop": true
}
}
// tsconfig.json (hereda y sobreescribe)
{
"extends": "./tsconfig.base.json",
"compilerOptions": {
"outDir": "./dist",
"rootDir": "./src"
},
"include": ["src/**/*"]
}La comunidad de TypeScript mantiene configuraciones base curadas en el paquete @tsconfig/bases:
npm install -D @tsconfig/node22{
"extends": "@tsconfig/node22/tsconfig.json",
"compilerOptions": {
"outDir": "./dist"
}
}Con la configuración correcta establecida, el compilador es tu aliado. En la siguiente lección comenzamos a explorar el sistema de tipos en sí: tipos primitivos, anotaciones y cuándo dejar que TypeScript infiera por ti.
Inicia sesión para guardar tu progreso