← Volver al blogTypeScript 7 ya es nativo: cómo migrar servicios Node sin romper tu toolchain
typescriptnodejstoolingperformancemigration

TypeScript 7 ya es nativo: cómo migrar servicios Node sin romper tu toolchain

TypeScript 7 lleva el compilador a Go. Una guía práctica para migrar servicios Node sin romper el tooling que todavía depende de TypeScript 6.

TypeScript 7 reemplaza el compilador que corría sobre Node.js por un port nativo escrito en Go. La mejora de rendimiento es enorme, pero todavía no conviene forzar la actualización en herramientas que dependen de la API programática del compilador.

Probé la migración de TypeScript 6.0.3 a 7.0.2 en dos servicios Node. Ambos pasaron type-check, build y construcción Docker sin cambiar una línea de código. Otro workspace del mismo monorepo permaneció intencionalmente en TypeScript 6 porque su checker todavía importa la API anterior. Esa diferencia resume la estrategia correcta para adoptar TypeScript 7 hoy.


TypeScript 7 no es una actualización normal del lenguaje. El equipo de Microsoft portó el compilador y el language server a Go para ejecutar el análisis de tipos como código nativo, aprovechar varios núcleos y reducir el costo de trabajar con proyectos grandes.

La intención no fue rediseñar el sistema de tipos. El nuevo compilador conserva la estructura y la lógica del anterior para producir resultados compatibles con TypeScript 6, pero cambia por completo la forma en la que se ejecuta.

Esa distinción importa. Para muchos servicios Node la migración puede ser tan sencilla como actualizar una dependencia. Para frameworks y herramientas que importan la API de TypeScript dentro de su propio proceso, todavía hay que esperar.

Qué cambió realmente

Hasta TypeScript 6, tsc era una aplicación escrita en TypeScript que se ejecutaba sobre Node.js. TypeScript 7 instala un ejecutable nativo construido desde el nuevo port en Go.

Arquitectura del compilador de TypeScript 6 frente al port nativo de TypeScript 7

El port conserva la lógica del compilador, pero cambia su base de ejecución y permite trabajo paralelo.

El resultado principal es rendimiento:

Proyecto TypeScript 6 TypeScript 7 Mejora
VS Code 125.7 s 10.6 s 11.9×
Sentry 139.8 s 15.7 s 8.9×
Playwright 12.8 s 1.47 s 8.7×
tldraw 11.2 s 1.46 s 7.7×

Comparación de tiempos de build entre TypeScript 6 y TypeScript 7

Los resultados oficiales muestran mejoras entre 7.7× y 11.9× en builds completos.

Son cifras publicadas por el equipo de TypeScript. También reportan reducciones de memoria de entre 6% y 26% en esos proyectos.

El cambio se siente en más lugares que un build de CI:

  • Carga inicial del proyecto en el editor.
  • Diagnósticos mientras escribes.
  • Autocompletado.
  • Búsqueda de referencias.
  • tsc --watch.
  • Builds con project references.

El nuevo compilador puede paralelizar parsing, type-checking y emisión. TypeScript 7 utiliza cuatro workers de type-checking por defecto y permite ajustar ese valor con el flag experimental --checkers.

La limitación importante: TypeScript 7 todavía no expone una API

TypeScript 7.0 incluye el CLI, el compilador y un language server basado en LSP, pero todavía no incluye una API programática estable.

Eso afecta a las herramientas que no se limitan a ejecutar tsc, sino que importan TypeScript para analizar código dentro de sus propios compiladores o language servers.

La documentación oficial menciona directamente estos ecosistemas:

  • Astro.
  • Vue.
  • Svelte.
  • MDX.
  • Angular para el análisis de templates.
  • Herramientas como typescript-eslint.

Un ejemplo actual es @astrojs/check 0.9.9, que todavía declara este peer dependency:

{
  "typescript": "^5.0.0 || ^6.0.0"
}

Forzar TypeScript 7 ahí solo para tener el número más reciente no aporta nada. Puede romper el checker o producir una combinación que sus mantenedores todavía no soportan.

Por eso un monorepo puede quedar así durante la transición:

Servicio Node A              TypeScript 7.0.2
Servicio Node B              TypeScript 7.0.2
Workspace con checker embebido  TypeScript 6.0.3

Un monorepo no necesita usar una única versión del compilador en todos sus paquetes. Cada workspace puede declarar la versión compatible con su toolchain.

Árbol de decisión para adoptar TypeScript 7 o mantener TypeScript 6

La migración depende de cómo cada herramienta consume TypeScript, no de mantener un número uniforme en todo el repositorio.

Migrar un servicio Node a TypeScript 7

Tomemos un servicio Node con esta configuración:

{
  "compilerOptions": {
    "target": "ES2022",
    "module": "NodeNext",
    "moduleResolution": "NodeNext",
    "lib": ["ES2022"],
    "outDir": "dist",
    "rootDir": "src",
    "strict": true,
    "noUncheckedIndexedAccess": true,
    "resolveJsonModule": true,
    "types": ["node"]
  },
  "include": ["src/**/*"],
  "exclude": ["dist", "node_modules"]
}

Esta configuración ya evita dos de las sorpresas más comunes de TypeScript 7:

  • rootDir está declarado explícitamente.
  • Los tipos globales necesarios están declarados en types.

TypeScript 7 adopta los nuevos defaults introducidos por TypeScript 6. Entre ellos, strict pasa a ser true, rootDir cambia su valor predeterminado y types pasa a [].

Ser explícito en tsconfig.json hace que el proyecto no dependa de defaults que pueden cambiar entre versiones.

La actualización con pnpm puede hacerse de forma acotada:

pnpm --filter api add -D typescript@7.0.2

En un proyecto npm independiente:

npm install --save-dev --save-exact typescript@7.0.2

Después hay que validar el flujo real, no solamente ejecutar tsc --version:

pnpm check
pnpm build
docker compose build api

En la prueba real, los dos servicios compilaron sin cambiar una línea de TypeScript. Venían de TypeScript 6, tenían strict, rootDir, types y NodeNext configurados explícitamente, así que la transición fue directa.

El lockfile crecerá y no significa que algo salió mal

TypeScript 7 distribuye ejecutables nativos para diferentes combinaciones de sistema operativo y arquitectura.

Al actualizar un proyecto npm, el lockfile incorporó paquetes opcionales con nombres similares a estos:

@typescript/typescript-darwin-arm64
@typescript/typescript-darwin-x64
@typescript/typescript-linux-arm64
@typescript/typescript-linux-x64
@typescript/typescript-win32-x64

No significa que npm instalará todos esos binarios en producción. Son dependencias opcionales y el package manager selecciona la que corresponde a la plataforma actual.

Es un cambio visible y esperado. Conviene conocerlo antes de revisar el pull request para no confundir un lockfile más grande con una actualización accidental.

TypeScript 6 y 7 pueden convivir

Microsoft publicó @typescript/typescript6 para herramientas que todavía necesitan la API anterior.

Una aplicación puede mantener TypeScript 6 bajo el nombre typescript y añadir el compilador nativo como otro paquete:

{
  "devDependencies": {
    "@typescript/native": "npm:typescript@7.0.2",
    "typescript": "npm:@typescript/typescript6@6.0.2"
  }
}

Con esta combinación:

  • npx tsc ejecuta TypeScript 7.
  • tsc6 sigue disponible para comparar resultados.
  • Las herramientas que importan typescript continúan recibiendo la API de TypeScript 6.

No siempre hace falta usar aliases. En un monorepo con paquetes independientes suele ser más sencillo mantener TypeScript 7 en los servicios Node y TypeScript 6 en los workspaces que todavía dependen de esa API.

Controlar el paralelismo en CI

TypeScript 7 usa cuatro workers de type-checking por defecto. --checkers y --builders son controles experimentales; conviene medirlos antes de incorporarlos a un script estable de CI.

En una máquina con varios núcleos se puede experimentar con:

tsc --checkers 8

En un runner pequeño o con memoria limitada conviene hacer lo contrario:

tsc --checkers 1

También existe un modo completamente secuencial:

tsc --singleThreaded

Para monorepos con project references, --builders controla cuántos proyectos pueden construirse en paralelo:

tsc --build --builders 2 --checkers 2

Hay que tratar ambos valores con cuidado. --builders 4 --checkers 4 puede levantar hasta dieciséis procesos de type-checking al mismo tiempo.

Mi recomendación inicial es conservar los defaults. Solo hay que ajustarlos después de medir CPU, memoria y tiempo total en el runner real.

Si vienes de TypeScript 5, no saltes directamente

TypeScript 7 convierte en errores varias opciones que fueron deprecadas en TypeScript 6.

Algunas de las más importantes:

  • target: "es5" ya no está soportado.
  • moduleResolution: "node" y "node10" ya no están soportados.
  • moduleResolution: "classic" fue eliminado.
  • module: "amd", "umd", "systemjs" y "none" fueron eliminados.
  • baseUrl ya no está soportado.
  • esModuleInterop no puede establecerse en false.
  • allowSyntheticDefaultImports no puede establecerse en false.

La ruta segura es:

TypeScript 5

TypeScript 6
    ↓ corregir deprecations y configuración
TypeScript 7

Un proyecto que compila limpiamente con TypeScript 6, usa stableTypeOrdering y no oculta deprecations debería producir resultados equivalentes con TypeScript 7.

Checklist de migración

Antes de actualizar:

  • Sube primero a TypeScript 6.
  • Elimina flags deprecados.
  • Declara rootDir.
  • Declara los paquetes necesarios en types.
  • Revisa plugins que importan la API de TypeScript.

Después de actualizar:

  • Ejecuta tsc --noEmit.
  • Ejecuta el build real.
  • Ejecuta las pruebas.
  • Construye la imagen Docker.
  • Revisa el crecimiento del lockfile.
  • Prueba el editor y --watch.
  • Mide antes de cambiar --checkers o --builders.

Conclusión

TypeScript 7 inaugura una etapa nueva para el ecosistema. El mayor cambio no es una sintaxis adicional, sino dejar de ejecutar el compilador como una aplicación JavaScript monohilo.

Para servicios Node con una configuración moderna, la migración puede ser sorprendentemente tranquila. En dos proyectos reales bastó actualizar de 6.0.3 a 7.0.2 y ejecutar los mismos gates: type-check, build y Docker.

La parte importante es no convertir la actualización en una carrera por uniformar versiones. Astro y otras herramientas embebidas todavía necesitan TypeScript 6 porque TypeScript 7.0 no expone la API que utilizan.

La mejor estrategia hoy es híbrida: TypeScript 7 donde el CLI es suficiente, TypeScript 6 donde el tooling todavía lo necesita, y una nueva revisión cuando TypeScript 7.1 publique la API programática.

Fuentes

Comentarios

Cargando comentarios…