Cómo Ejecutar TypeScript de Forma Nativa en Node.js

Node.js 23.6.0 marca un punto de inflexión para los desarrolladores de TypeScript: ahora puedes ejecutar archivos .ts
directamente sin herramientas de transpilación como ts-node o tsc. Este soporte nativo de TypeScript optimiza los flujos de trabajo de desarrollo al eliminar los pasos de compilación mientras mantiene la seguridad de tipos a través de tu IDE.
Esta guía cubre todo lo que necesitas para ejecutar TypeScript de forma nativa en Node.js, desde la configuración básica hasta consideraciones de producción. Aprenderás cómo funciona la eliminación de tipos, qué características de TypeScript están soportadas y cómo configurar tus proyectos para una compatibilidad óptima.
Puntos Clave
- Node.js 23.6.0 ejecuta archivos TypeScript directamente sin transpilación
- La eliminación de tipos remueve anotaciones mientras preserva la estructura del código
- La mayoría de las características comunes de TypeScript funcionan, pero los enums y namespaces requieren soluciones alternativas
- Las declaraciones de importación deben incluir la extensión
.ts
- La ejecución nativa ofrece tiempos de inicio 2-3x más rápidos comparado con herramientas tradicionales
Inicio Rápido: Ejecutando TypeScript en Node.js 23.6.0
Comencemos con un archivo TypeScript simple para demostrar la ejecución nativa:
// greeting.ts
function greet(name: string): string {
return `Hello, ${name}!`
}
console.log(greet("TypeScript"))
Con Node.js 23.6.0 o posterior, ejecuta esto directamente:
node greeting.ts
Eso es todo—no se requiere paso de compilación. Node.js elimina las anotaciones de tipo y ejecuta el JavaScript restante.
Para verificar tu versión de Node.js:
node --version # Debería ser v23.6.0 o superior
Verás una advertencia experimental en la primera ejecución:
ExperimentalWarning: Type Stripping is an experimental feature and might change at any time
Para suprimir esta advertencia en desarrollo:
node --disable-warning=ExperimentalWarning greeting.ts
O configurarlo permanentemente:
export NODE_OPTIONS="--disable-warning=ExperimentalWarning"
Entendiendo la Eliminación de Tipos en Node.js
La eliminación de tipos difiere fundamentalmente de la transpilación tradicional de TypeScript. En lugar de transformar TypeScript en JavaScript, Node.js simplemente remueve las anotaciones de tipo mientras preserva la estructura original del código.
Esto es lo que sucede durante la eliminación de tipos:
// TypeScript original
function calculate(a: number, b: number): number {
return a + b
}
// Después de la eliminación de tipos (lo que Node.js ejecuta)
function calculate(a , b ) {
return a + b
}
Observa la preservación de espacios en blanco—esto mantiene números de línea precisos para depuración sin requerir source maps.
Beneficios de Rendimiento
La ejecución nativa de TypeScript ofrece mejoras significativas de rendimiento:
- Sin sobrecarga de transpilación: Ejecución directa sin pasos intermedios
- Tiempos de inicio más rápidos: ~45ms vs. 120ms con ts-node
- Uso reducido de memoria: Sin transpilador cargado en memoria
- Depuración simplificada: Números de línea originales preservados
Evolución del Soporte de TypeScript en Node.js
Entender la progresión te ayuda a elegir el enfoque correcto:
v22.6.0: Eliminación Inicial de Tipos
node --experimental-strip-types app.ts
Solo eliminación básica de tipos—sin soporte de sintaxis específica de TypeScript.
v22.7.0: Transformación de Tipos
node --experimental-transform-types app.ts
Se agregó soporte para enums y namespaces a través de transformación.
v23.6.0: Eliminación de Tipos por Defecto
node app.ts # Eliminación de tipos habilitada por defecto
No se necesita bandera para ejecución básica de TypeScript.
Características de TypeScript Soportadas y Limitaciones
Lo que Funciona
TypeScript nativo en Node.js soporta la mayoría de las características cotidianas de TypeScript:
// ✅ Anotaciones de tipo
let count: number = 0
// ✅ Interfaces
interface User {
id: number
name: string
}
// ✅ Alias de tipo
type Status = 'active' | 'inactive'
// ✅ Genéricos
function identity<T>(value: T): T {
return value
}
// ✅ Importaciones de tipo
import type { Config } from './types.ts'
Lo que No Funciona
Algunas características específicas de TypeScript requieren soluciones alternativas:
Característica | Soportada | Solución Alternativa |
---|---|---|
Enums | ❌ | Usar tipos unión u objetos const |
Namespaces | ❌ | Usar módulos ES |
Propiedades de parámetros | ❌ | Declaraciones explícitas de propiedades |
JSX/TSX | ❌ | Usar transpilación tradicional |
Decoradores | ❌ | Esperar soporte de V8 |
Ejemplos de soluciones alternativas:
// ❌ Enum (no soportado)
enum Status {
Active,
Inactive
}
// ✅ Alternativa con tipo unión
type Status = 'active' | 'inactive'
// ✅ Alternativa con objeto const
const Status = {
Active: 'active',
Inactive: 'inactive'
} as const
Discover how at OpenReplay.com.
Extensiones de Archivo y Sistemas de Módulos
Node.js usa extensiones de archivo para determinar el manejo de módulos:
.ts
- Sigue el campo"type"
de package.json (ESM o CommonJS).mts
- Siempre tratado como ESM.cts
- Siempre tratado como CommonJS
Importante: Las importaciones locales deben incluir la extensión .ts
:
// ❌ TypeScript tradicional
import { utils } from './utils'
// ✅ TypeScript nativo de Node.js
import { utils } from './utils.ts'
Configurando tsconfig.json para TypeScript Nativo
Aunque Node.js no lee tsconfig.json durante la ejecución, una configuración adecuada asegura soporte del IDE y verificación de tipos:
{
"compilerOptions": {
"target": "esnext",
"module": "nodenext",
"moduleResolution": "nodenext",
"allowImportingTsExtensions": true,
"rewriteRelativeImportExtensions": false,
"verbatimModuleSyntax": true,
"strict": true,
"noEmit": true
}
}
Configuraciones clave explicadas:
allowImportingTsExtensions
: Permite.ts
en rutas de importaciónrewriteRelativeImportExtensions
: Configurado en false para preservar extensiones.ts
verbatimModuleSyntax
: Fuerza importaciones de tipo explícitasnoEmit
: Previene generación accidental de JavaScript
Ejecuta verificación de tipos por separado:
tsc --noEmit
Guía de Migración desde Herramientas Tradicionales de TypeScript
Migrando desde ts-node
- Remover dependencia de ts-node:
npm uninstall ts-node
- Actualizar scripts de package.json:
// Antes
"scripts": {
"dev": "ts-node src/index.ts"
}
// Después
"scripts": {
"dev": "node src/index.ts"
}
- Manejar características no soportadas (convertir enums a uniones)
Migrando desde Compilación tsc
- Remover pasos de compilación:
// Remover estos scripts
"scripts": {
"build": "tsc",
"start": "node dist/index.js"
}
// Usar esto en su lugar
"scripts": {
"start": "node src/index.ts"
}
- Actualizar pipelines de CI/CD para omitir compilación
Comparación de Rendimiento
La ejecución nativa de TypeScript muestra mejoras significativas:
Métrica | TypeScript Nativo | ts-node | tsc + node |
---|---|---|---|
Tiempo de inicio | ~45ms | ~120ms | ~200ms |
Uso de memoria | Línea base | +30MB | +10MB |
Paso de compilación | Ninguno | Ninguno | Requerido |
Errores Comunes y Soluciones
Errores de Ruta de Importación
// Error: Cannot find module './utils'
import { helper } from './utils'
// Solución: Incluir extensión .ts
import { helper } from './utils.ts'
Sintaxis No Soportada
// Error: Enums are not supported
enum Color { Red, Blue }
// Solución: Usar objeto const
const Color = { Red: 0, Blue: 1 } as const
Confusión con Verificación de Tipos
Recuerda: Node.js no realiza verificación de tipos. Siempre ejecuta tsc --noEmit
para validación de tipos.
Consideraciones de Producción
Cuándo Usar TypeScript Nativo
- Entornos de desarrollo
- Prototipos y experimentos
- Scripts pequeños y utilidades
- Equipos listos para características experimentales
Cuándo Evitarlo
- Aplicaciones de producción (hasta que sea estable)
- Proyectos que requieren características completas de TypeScript
- Equipos que necesitan herramientas estables
- Pipelines de compilación complejos
Ajustes de Docker
# Antes
FROM node:23-alpine
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
CMD ["node", "dist/index.js"]
# Después
FROM node:23-alpine
COPY package*.json ./
RUN npm ci
COPY . .
CMD ["node", "src/index.ts"]
Conclusión
El soporte nativo de TypeScript en Node.js 23.6.0 representa una simplificación significativa para los flujos de trabajo de desarrollo. Al eliminar los pasos de transpilación, puedes enfocarte en escribir código en lugar de configurar herramientas de compilación. Aunque existen limitaciones—particularmente alrededor de sintaxis específica de TypeScript—los beneficios para la mayoría de escenarios de desarrollo son convincentes.
Comienza probando TypeScript nativo en tu entorno de desarrollo, migra gradualmente proyectos existentes y prepárate para un futuro donde TypeScript se ejecute en cualquier lugar donde JavaScript lo haga. Mientras esta característica se estabiliza, espera una adopción más amplia y capacidades expandidas en próximas versiones de Node.js.
Preguntas Frecuentes
Aunque técnicamente es posible, aún no se recomienda para uso en producción. La característica sigue siendo experimental y puede cambiar. Úsala para entornos de desarrollo, prototipos y aplicaciones no críticas. Para producción, continúa usando transpilación tradicional hasta que la característica se vuelva estable.
Sí, debes mantener TypeScript como dependencia de desarrollo para verificación de tipos. Node.js solo elimina tipos sin validarlos. Ejecuta tsc --noEmit por separado para capturar errores de tipo durante el desarrollo o en tu pipeline de CI.
TypeScript nativo requiere extensiones .ts explícitas en rutas de importación, a diferencia de las herramientas tradicionales de TypeScript. Actualiza todas las importaciones locales de './module' a './module.ts'. Las importaciones de paquetes externos no necesitan extensiones.
Reemplaza enums con tipos unión para casos simples u objetos const con aserción as const para enums numéricos. Para enums de string, los tipos unión funcionan perfectamente. Este enfoque es realmente más tree-shakeable y se alinea mejor con las prácticas modernas de TypeScript.
El equipo de Node.js se enfoca en eliminación de tipos en lugar de transpilación completa por razones de rendimiento. Las características que requieren transformación en tiempo de ejecución como enums y decoradores pueden obtener soporte cuando V8 las implemente nativamente, pero el objetivo es procesamiento rápido y mínimo en lugar de compatibilidad completa con TypeScript.
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.