Node.js ejecuta JavaScript. Siempre ha sido así, y en 2026 sigue siendo así. Lo que ha cambiado es que cada vez hay más formas de ejecutar TypeScript directamente, sin el paso previo de compilar con tsc. Algunas son nativas de Node, otras son herramientas externas, y una es un runtime completamente distinto. Aquí las tienes todas, con sus diferencias claras.
El problema de fondo: TypeScript y Node.js no hablan el mismo idioma
TypeScript añade tipos a JavaScript, pero los motores de JavaScript no entienden esa sintaxis. Para que Node.js pueda ejecutar un archivo .ts hace falta un paso intermedio: eliminar o transpilat las anotaciones de tipo y dejar JavaScript puro.
Históricamente, el flujo era: escribes TypeScript, ejecutas tsc, obtienes archivos .js en una carpeta dist/, y luego ejecutas esos archivos con Node. Para producción tiene todo el sentido. Para desarrollo, es lento y molesto si tienes que repetirlo con cada cambio.
De ahí surgieron herramientas como ts-node, que hacen la transpilación en memoria al vuelo. Y de ahí viene también el soporte nativo que Node ha ido incorporando desde la versión 22.6.
Node.js con strip types nativo (22.6+ y 23+)
Desde Node.js 22.6 puedes ejecutar archivos TypeScript directamente con un flag experimental:
node --experimental-strip-types mi-archivo.ts
En Node.js 23 el flag pasó a llamarse --strip-types y quedó activo por defecto para archivos .ts, así que esto ya funciona sin flags adicionales:
node mi-archivo.ts
Lo que hace Node internamente es eliminar las anotaciones de tipo del archivo antes de ejecutarlo. Ojo: no hace type checking. No te va a avisar si tienes un error de tipos. Solo quita las anotaciones y ejecuta el JavaScript resultante. Es más un preprocesador que un compilador.
Eso trae una limitación importante: no soporta toda la sintaxis de TypeScript. Concretamente, no puede con enum, namespace ni import type = require(...), porque esas construcciones no son simplemente "tipos que se borran", sino que generan código JavaScript real. Node solo sabe eliminar lo que no afecta a la lógica.
Si quieres asegurarte de que tu código es compatible con strip types nativo, añade esta opción al tsconfig.json:
{
"compilerOptions": {
"erasableSyntaxOnly": true
}
}
Con eso, el compilador de TypeScript te avisará si usas alguna construcción que Node no puede eliminar.
tsx: la alternativa rápida sin salir de Node
Si el soporte nativo de Node te parece demasiado restrictivo, tsx es probablemente la mejor opción en 2026. Internamente usa esbuild para transpilat TypeScript, lo que lo hace muy rápido, y soporta toda la sintaxis de TypeScript incluyendo enum y namespace.
La instalación es sencilla:
npm install -g tsx
# o sin instalar globalmente
npx tsx mi-archivo.ts
Para ejecutar un archivo:
tsx mi-archivo.ts
Para scripts que quieres ejecutar directamente desde la terminal, puedes usar tsx como shebang:
#!/usr/bin/env tsx
console.log("Hola desde TypeScript");
Y para desarrollo con recarga automática:
tsx watch src/index.ts
tsx no hace type checking tampoco. Si necesitas que te avise de errores de tipos mientras desarrollas, tendrás que correr tsc --noEmit por separado o configurar tu editor para que lo haga. tsx solo se ocupa de ejecutar el código lo más rápido posible.
Más información en tsx.is.
ts-node: el original, con type checking opcional
ts-node fue durante años la herramienta de referencia para ejecutar TypeScript en Node. Sigue siendo una opción válida, aunque en proyectos nuevos tsx o el soporte nativo de Node le han comido bastante terreno.
La diferencia principal con tsx es que ts-node usa el compilador oficial de TypeScript (tsc), no esbuild. Eso lo hace más lento en el arranque, pero también más fiel al comportamiento del compilador oficial.
Por defecto, ts-node hace type checking completo:
ts-node mi-archivo.ts
Si quieres velocidad y no te importa el type checking durante la ejecución:
ts-node --transpile-only mi-archivo.ts
Para proyectos con módulos ES:
ts-node-esm mi-archivo.ts
¿Cuándo tiene sentido usar ts-node en 2026? Cuando necesitas type checking durante la ejecución de scripts, por ejemplo en scripts de CI que validan la integridad de datos, o cuando ya tienes un proyecto configurado con ts-node y el coste de migrar no compensa.
Bun: TypeScript sin configurar nada
Bun es un runtime JavaScript alternativo a Node.js que trata TypeScript como un ciudadano de primera clase desde el primer día. Sin flags, sin instalar nada extra, sin configuración:
bun run mi-archivo.ts
Funciona. Punto.
Bun usa JavaScriptCore (el motor de Safari) y transpila TypeScript internamente, también sin type checking. Para hot reload con estado preservado entre recargas:
bun --hot mi-archivo.ts
La propuesta de valor de Bun es la simplicidad total: un solo binario que hace de runtime, bundler, test runner y gestor de paquetes. Si empiezas un proyecto desde cero y no tienes restricciones sobre el runtime, Bun elimina prácticamente toda la configuración inicial.
La contrapartida es la compatibilidad. Bun no es 100% compatible con todas las APIs de Node.js, y algunos paquetes de npm que dependen de APIs nativas de Node pueden no funcionar bien. Para la mayoría de proyectos web o de scripting no es un problema, pero conviene tenerlo en cuenta.
Comparativa: cuándo usar cada uno
- Node.js nativo (--strip-types / Node 23+): cuando ya estás en Node 23+ y tu código solo usa sintaxis erasable (nada de
enumninamespace). Cero dependencias extra, cero configuración. - tsx: cuando necesitas
enumo quieres la opción más rápida sin salir del ecosistema Node. Es el sustituto más directo de ts-node para proyectos existentes. - ts-node: cuando necesitas type checking durante la ejecución, o cuando ya tienes un proyecto configurado y no quieres cambiar nada.
- Bun: cuando empiezas un proyecto nuevo y quieres el setup más simple posible, sin preocuparte de configurar Node ni instalar herramientas adicionales.
Configurar package.json para scripts TypeScript
Un ejemplo práctico de cómo configurar los scripts de npm para combinar tsx en desarrollo con Node nativo en producción:
{
"type": "module",
"scripts": {
"start": "node --strip-types src/index.ts",
"dev": "tsx watch src/index.ts",
"build": "tsc",
"typecheck": "tsc --noEmit"
}
}
Para producción, lo recomendable sigue siendo compilar con tsc o tsup y ejecutar el JavaScript resultante. Ejecutar tsx o ts-node en producción añade overhead en el arranque y no te da las ventajas de un build optimizado.
El tsconfig mínimo para Node.js en 2026
Si creas un proyecto nuevo, este es un punto de partida razonable para un servidor Node.js moderno:
{
"compilerOptions": {
"target": "ES2022",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"erasableSyntaxOnly": true
}
}
Algunos apuntes sobre estas opciones:
"module": "NodeNext"junto con"moduleResolution": "NodeNext"hace que TypeScript respete los camposexportsdepackage.json, que es como Node resuelve los módulos desde la versión 12."target": "ES2022"evita transpilat características que Node 18+ ya soporta de forma nativa, comoasync/await, optional chaining o nullish coalescing."erasableSyntaxOnly": truegarantiza compatibilidad con strip types nativo. Si luego decides migrar a Node 23 sin tsx, no tendrás que tocar el código.
Si usas Bun, el tsconfig puede ser incluso más mínimo porque Bun no depende de él para la ejecución, solo lo usa como referencia para el editor.
El panorama en 2026
La tendencia es clara: ejecutar TypeScript directamente, sin un paso de compilación en desarrollo, se está convirtiendo en lo habitual. Node lo soporta de forma nativa, Bun lo ha soportado siempre, y tsx cubre los casos que Node nativo no puede manejar.
Si te interesa saber más sobre las novedades recientes de TypeScript como lenguaje, tienes un buen resumen en TypeScript y las herramientas del 2025. Y si quieres entender mejor la historia del JavaScript en el servidor, JavaScript en el servidor: de Node.js a Bun da bastante contexto.
Imagen: Pexels / Vladimir Srajber
