TypeScript en Node: La Configuración Práctica
Ya escribes TypeScript para el navegador. Ahora lo necesitas ejecutando del lado del servidor—para una API, un script de build o SSR. El problema: la mayoría de las guías de configuración están desactualizadas, recomendando configuraciones CommonJS o herramientas que no se alinean con Node.js moderno.
Esta guía cubre dos enfoques para tu configuración de TypeScript en Node.js: compilar con tsc y ejecutar JavaScript, o ejecutar archivos .ts directamente con la eliminación nativa de tipos de Node. Ambos funcionan. Cada uno se ajusta a diferentes escenarios.
Puntos Clave
- Establece
"type": "module"en package.json para habilitar ESM por defecto en proyectos modernos de TypeScript en Node.js - Usa compilación con
tscpara despliegues en producción, paquetes publicados y código que utiliza enums, namespaces o parameter properties - Usa la eliminación nativa de tipos de Node para scripts locales, servidores de desarrollo y prototipos rápidos
- Siempre usa
import typepara importaciones de solo tipos para evitar errores en tiempo de ejecución con la eliminación de tipos - Ejecuta
tsc --noEmiten CI ya que la eliminación de tipos de Node no realiza verificación de tipos
La Base: Node 24 LTS y ESM
Comienza con esta base:
{
"type": "module"
}
Esto habilita ESM por defecto. Tus importaciones usan sintaxis ESM, y Node resuelve los módulos en consecuencia.
Node 24 es la línea base LTS actual para esta configuración (se puede descargar desde aquí: https://nodejs.org/en/download).
Enfoque 1: Compilar con tsc, Ejecutar JavaScript
Este enfoque separa la compilación de la ejecución. Úsalo para despliegues en producción, paquetes publicados o cuando necesites soporte completo de características de TypeScript.
tsconfig para Node 24
{
"compilerOptions": {
"target": "ES2024",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"rootDir": "src",
"outDir": "dist",
"strict": true,
"skipLibCheck": true,
"declaration": true,
"sourceMap": true,
"verbatimModuleSyntax": true,
"isolatedModules": true,
"lib": ["ES2024"]
},
"include": ["src"],
"exclude": ["node_modules", "dist"]
}
Configuraciones clave en esta configuración:
module: NodeNextymoduleResolution: NodeNext: Coincide con el comportamiento real de resolución de módulos de NodeverbatimModuleSyntax: Requiereimport typeexplícito para importaciones de solo tipos—crítico para evitar errores en tiempo de ejecución (ver documentación de TypeScript: https://www.typescriptlang.org/tsconfig#verbatimModuleSyntax)isolatedModules: Asegura compatibilidad con herramientas de transpilación de archivos individuales
Scripts
{
"scripts": {
"build": "tsc",
"start": "node dist/index.js",
"dev": "tsc --watch"
}
}
Ejecuta npm run build, luego npm start. El JavaScript compilado reside en dist/.
Enfoque 2: TypeScript Nativo de Node (Eliminación de Tipos)
Node introdujo soporte nativo de TypeScript en Node 22 y lo estabilizó en Node 24 LTS mediante la eliminación de tipos. Úsalo para scripts, herramientas locales o desarrollo cuando quieras cero pasos de build.
Documentación oficial: https://nodejs.org/api/typescript.html
Cómo Funciona
En Node 24+, ejecuta directamente:
node src/index.ts
(Las versiones antiguas de Node requerían flags experimentales; Node 24 no los necesita.)
Limitaciones Críticas
El TypeScript nativo de Node solo elimina tipos—no verifica tipos. Aún necesitas tsc --noEmit en CI o tu editor para detectar errores.
Otras restricciones:
- Ignora tsconfig.json: Node no lee tus opciones del compilador
- Requiere extensiones de archivo explícitas: Escribe
import { foo } from './utils.js'incluso cuando el archivo fuente esutils.ts - Respeta las reglas de ESM vs CJS: El campo type de tu
package.jsonimporta - No ejecutará TypeScript desde node_modules: Las dependencias deben ser JavaScript compilado
- Solo soporta sintaxis borrable: Enums, namespaces y parameter properties fallan a menos que habilites
--experimental-transform-types
Las Extensiones de Archivo Importan
Para formatos de módulos mixtos:
- Archivos
.mts→ siempre ESM - Archivos
.cts→ siempre CommonJS - Archivos
.ts→ siguen el campo type depackage.json
Discover how at OpenReplay.com.
Evitando Errores en Tiempo de Ejecución
Usa import type para importaciones de solo tipos:
// Correcto
import type { Request, Response } from 'express'
import express from 'express'
// Incorrecto - fallará en tiempo de ejecución con eliminación de tipos
import { Request, Response } from 'express'
Habilita verbatimModuleSyntax en tu tsconfig para detectar estos durante el desarrollo, aunque Node ignore la configuración en tiempo de ejecución.
Qué Enfoque Usar
Usa compilación con tsc para:
- Despliegues en producción
- Paquetes npm publicados
- Código que usa enums, namespaces o parameter properties
- Proyectos que requieren source maps en producción
Usa eliminación nativa de tipos para:
- Scripts locales y herramientas
- Servidores de desarrollo (combina con
--watch) - Prototipos rápidos
- Builds de desarrollo SSR
Una Configuración Práctica de Desarrollo
Combina ambos enfoques:
{
"scripts": {
"dev": "node --watch src/index.ts",
"typecheck": "tsc --noEmit",
"build": "tsc",
"start": "node dist/index.js"
}
}
El desarrollo usa ejecución nativa para velocidad. CI ejecuta typecheck. Producción despliega JavaScript compilado.
Conclusión
La configuración moderna de TypeScript en Node.js es más simple de lo que sugieren las guías antiguas. Usa ESM, configura la resolución de módulos NodeNext, y elige tu estrategia de ejecución según el contexto. La eliminación nativa de tipos funciona para desarrollo y scripts. La salida compilada funciona para producción y paquetes. Ambos enfoques comparten el mismo código fuente y tsconfig—no estás atado a ninguno de los dos.
Preguntas Frecuentes
La resolución de módulos de Node requiere extensiones de archivo explícitas para ESM. Cuando escribes import from ./utils.js, Node busca esa ruta exacta en tiempo de ejecución, incluso si tu archivo fuente es utils.ts. Dado que la eliminación de tipos remueve tipos pero no renombra archivos, y tsc genera archivos .js, usar extensiones .js en tu código fuente asegura que las importaciones funcionen en ambos escenarios.
No por defecto. Los enums requieren transformación de código, no solo eliminación de tipos. Puedes habilitar el flag --experimental-transform-types para soportar enums, namespaces y parameter properties, pero esto añade complejidad. Para configuraciones más simples, considera usar objetos const con aserciones as const como alternativa a los enums.
Para la mayoría de los casos de uso, no. La eliminación nativa de tipos de Node 24 maneja la ejecución directa de .ts. Herramientas como ts-node y tsx son conveniencias opcionales que añaden soporte para tsconfig.json, resolución de alias de rutas y transformaciones completas de TypeScript sin flags. Úsalas solo si tu configuración necesita esas características.
Cuando usas eliminación nativa de tipos, Node ejecuta tus archivos .ts directamente, por lo que los números de línea en los stack traces coinciden con tu código fuente. Para código compilado, habilita sourceMap en tsconfig.json y Node usará automáticamente los archivos .js.map para mostrar las ubicaciones originales de TypeScript en errores y sesiones del depurador.
Complete picture for complete understanding
Capture every clue your frontend is leaving so you can instantly get to the root cause of any issue with OpenReplay — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data.
Check our GitHub repo and join the thousands of developers in our community.