Back

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

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ísticaSoportadaSolución Alternativa
EnumsUsar tipos unión u objetos const
NamespacesUsar módulos ES
Propiedades de parámetrosDeclaraciones explícitas de propiedades
JSX/TSXUsar transpilación tradicional
DecoradoresEsperar 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

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ón
  • rewriteRelativeImportExtensions: Configurado en false para preservar extensiones .ts
  • verbatimModuleSyntax: Fuerza importaciones de tipo explícitas
  • noEmit: 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

  1. Remover dependencia de ts-node:
npm uninstall ts-node
  1. Actualizar scripts de package.json:
// Antes
"scripts": {
  "dev": "ts-node src/index.ts"
}

// Después
"scripts": {
  "dev": "node src/index.ts"
}
  1. Manejar características no soportadas (convertir enums a uniones)

Migrando desde Compilación tsc

  1. 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"
}
  1. Actualizar pipelines de CI/CD para omitir compilación

Comparación de Rendimiento

La ejecución nativa de TypeScript muestra mejoras significativas:

MétricaTypeScript Nativots-nodetsc + node
Tiempo de inicio~45ms~120ms~200ms
Uso de memoriaLínea base+30MB+10MB
Paso de compilaciónNingunoNingunoRequerido

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.

OpenReplay