Inicio / Artículos / Por qué la versión basada en Go de TypeScript 7 dañó los linters y las herramientas de los frameworks.

Por qué la versión basada en Go de TypeScript 7 dañó los linters y las herramientas de los frameworks.

Explica por qué el compilador más rápido de TypeScript 7, basado en Go, viene con una API incompatible que daña los linters, las instalaciones y las actualizaciones de Vue/Svelte en todo el ecosistema.

3041 palabras

Se lanzó el compilador. La API que se suponía debía venir con él no lo hizo.

Microsoft publicó TypeScript 7.0 el 8 de julio de 2026, y el titular prácticamente se escribió solo: diez veces más rápido. El compilador pasó de JavaScript a Go, funcionando en múltiples hilos y procesando bases de código que antes requerían dos minutos completos para ser compiladas, ahora terminándolo incluso antes de que pudieras cambiar a otra ventana. Casi todas las newsletters sobre este lanzamiento comenzaban con ese mismo gráfico de pruebas.

Luego los desarrolladores ejecutaron realmente npm install.

Lo que recibió muchos de ellos fue un binario rápido instalado sobre una cadena de herramientas defectuosa. Y la deficiencia no era sutil: los análisis de código se colapsaban al intentar leer una propiedad simple. Los gestores de paquetes rechazaban por completo la instalación debido a una discrepancia en el rango de dependencias. Los proyectos Vue y Svelte no podían actualizarse en absoluto. Un mes después, la situación sigue siendo prácticamente la misma, y no hay fecha prevista para una solución en ninguna de las versiones actualmente programadas.

Esa es la parte de la historia que quedó oculta, y es precisamente ella la que determina si realmente deberías realizar esta actualización ahora mismo.

La cifra que todos mencionan

Hay que reconocer primero el mérito correspondiente, ya que las mejoras de rendimiento no son solo un recurso publicitario. Microsoft publicó sus propios números de pruebas de rendimiento en el anuncio del lanzamiento, y son lo suficientemente detallados como para poder verificarlos.

El equipo informa aceleraciones en el rango de 8x a 12x en las compilaciones completas, y el uso de memoria disminuyó en realidad en lugar de aumentar, lo cual es lo opuesto al equilibrio habitual que uno esperaría. Slack le dijo a Microsoft que la verificación de tipos en su pipeline de CI pasó de aproximadamente siete minutos y medio a poco más de un minuto, y que su experiencia con el editor pasó de ser apenas utilizable a cargarse en cuestión de segundos. Canva informó que el tiempo necesario para ver el primer error en el editor disminuyó de unos 58 segundos a menos de 5.

Estos son logros técnicos reales, fruto de un año de trabajo continuo. Nada de lo que sigue resta valor a eso.

Se trató de una adaptación, no de una reescritura

Aquí está el detalle técnico que la mayoría de las coberturas pasaron por alto, y es ese detalle el que explica todo lo demás.

TypeScript 7 es una adaptación, no una reescritura desde cero. El equipo tradujo el compilador existente, archivo por archivo, de TypeScript a Go, preservando deliberadamente la estructura y lógica originales para que el comportamiento de verificación de tipos permaneciera idéntico. Se espera que todo lo que se compilaba sin problemas en la versión 6.0 se compile de manera similar en la 7.0. Así es como Microsoft logró lanzar un compilador de esta envergadura sin una serie de regresiones en su funcionamiento, lo cual refleja la verdadera disciplina con la que se llevó a cabo la adaptación.

Pero un compilador es en realidad dos productos separados que comparten un mismo nombre. Está el binario al que se invoca, tsc. Y está la biblioteca que otras herramientas incluyen como dependencia. Los linters, los transformadores de pruebas, los codemods basados en árboles sintácticos y los verificadores de plantillas no ejecutan tsc ni analizan el texto que este imprime. En su lugar, importan TypeScript directamente, recorren su árbol sintáctico con él y obtienen la información de tipos directamente del verificador.

La portada transmitió fielmente el primer producto. No transmitió en absoluto el segundo.

El propio compilador llegó intacto. La API de la que dependen todas las herramientas circundantes no lo acompañó en el proceso.

La línea oculta cerca del final de las notas de lanzamiento

Para ser justos con Microsoft, esto no se ocultó. Si lees el anuncio de 7.0, aproximadamente a dos tercios del texto, debajo de la sección que explica cómo ejecutar 7.0 junto con 6.0, hay una frase sobre la cual gran parte del ecosistema habló durante todo julio: TypeScript 7.0 se lanza sin una API.

Eso representa una brecha significativa. Microsoft afirma que está desarrollando una nueva API y planea ponerla a disposición en la versión 7.1. Según el equipo, ahora que el trabajo de adaptación está completo, están volviendo a centrarse en lanzar nuevas funcionalidades.

El ritmo establecido es un nuevo lanzamiento cada tres a cuatro meses. Si se mantiene ese cronograma, la versión 7.1 llegaría alrededor de octubre. Eso es todo lo que se sabe por ahora; aún no hay fecha confirmada para cuando esté lista la API de reemplazo.

Lea el anuncio de arriba hacia abajo y el patrón se hará claro. Primero aparece una tabla que muestra cuán más rápido funciona 7.0. Luego vienen citas destacadas de grandes empresas. Solo después Microsoft señala, casi de pasada, que una parte considerable del ecosistema de herramientas simplemente aún no puede ejecutarse en esta versión.

Ese orden fue una elección editorial deliberada, no un intento de engañar a nadie. Pero también es la razón por la cual muchos equipos descubrieron la brecha en la API a través de un registro de errores en su terminal, y no directamente del propio post del anuncio.

Problema 12518

El artefacto más útil que surgió de la semana de lanzamiento no fue una prueba de rendimiento, sino un informe de errores.

El día en que el nuevo compilador se puso a disposición del público, alguien que actualizaba un proyecto Vite plus React de 6.0.3 a 7.0.2 abrió el problema 12518 contra typescript-eslint, incluyendo una reproducción del error. En él se documentaron dos fallos separados.

El primero fue que npm ci se negó por completo a instalarlo, ya que la metadatos del paquete typescript-eslint establecían un rango de dependencias compatibles del cual 7.0.2 quedaba fuera. El segundo, para quienes insistieron en realizar la instalación de todos modos, fue que ESLint dejó de funcionar dentro de typescript-eslint al compilar el programa, porque el código intentaba acceder a una propiedad de la API del compilador que ya no existía en esta versión.

Los mantenedores cerraron el problema. No porque no les importara, sino porque no había nada que pudieran hacer al respecto.

Leído de forma aislada, parece despectivo. Pero no lo es. Los mantenedores de typescript-eslint no tienen forma de solucionarlo por sí mismos, ya que la pieza necesaria aún no se ha lanzado. Cerrar el problema fue simplemente una declaración honesta de los hechos: el verdadero trabajo corresponde a TypeScript 7.1, no al linter. Eso significa que la herramienta de TypeScript más utilizada en el ecosistema actualmente es incapaz de hacer algo respecto a su propia compatibilidad.

El equipo principal de ESLint abrió un problema correspondiente al día siguiente, confirmó que tiene la intención de abordarlo y también se encuentra atascado esperando esa misma pieza faltante. Los mantenedores de las herramientas de Vue se encuentran en la misma situación. Todos los que dependen de ellas están bloqueados por esa misma dependencia aún no lanzada.

El radio de impacto

Cualquier paquete que importe typescript y acceda a sus componentes internos está expuesto a esto. Concretamente:

  • typescript-eslint, junto con todas las reglas de validación conscientes de tipos desarrolladas sobre él. Esto genera errores evidentes, ya sea durante la instalación o en la primera ejecución; no pasará desapercibido.
  • ts-jest y cualquier transformador basado en llamadas al compilador interno. En comparación, esto produce errores de forma silenciosa, manifestándose como errores de transformación confusos en lugar de un fallo de instalación, lo cual es quizás peor porque parece un problema con la configuración de las pruebas en lugar de una incompatibilidad de versiones.
  • ts-morph y cualquier codemod personalizado desarrollado sobre él. Esta es la categoría más arriesgada. La introspección profunda de tipos puede deteriorarse de forma silenciosa, generando resultados ligeramente incorrectos en lugar de un fallo evidente. Realice una auditoría cuidadosa antes de ejecutar cualquier acción que pueda dañar un código base.
  • Verificación de plantillas basada en Volar, que abarca Vue, Svelte, Astro y MDX. Microsoft indica directamente en las notas de lanzamiento que estos flujos de trabajo probablemente no podrán ejecutarse con TypeScript 7 por el momento, y aconseja seguir utilizando la versión 6.0 para obtener soporte en el editor.
  • La verificación de plantillas de Angular, sujeta a la misma restricción, cuenta con una solución documentada oficialmente: ejecutar la versión 7.0 desde la línea de comandos para una rápida verificación de errores en todo el proyecto, pero mantener la versión 6.0 en el editor.
  • Cargadores de webpack. Las versiones antiguas de ts-loader siguen utilizando la API heredada. Una persona que comentó sobre el anuncio resumió el estado general: hay entusiasmo por actualizar, pero como la mayoría de los proyectos utilizan webpack y aún no existe una API compatible para los cargadores, todos esperan a la versión 7.1.
  • Mire con atención lo que hay en esa lista. Nada de ello son herramientas especializadas o exóticas: se trata del conjunto de herramientas estándar de un equipo front-end típico que trabaja hoy en día.

    El compilador en sí es estable. El ecosistema que lo rodea, no. Son dos estados de lanzamiento distintos que comparten un mismo número de versión.

    La solución de Microsoft: instalar dos compiladores a la vez

    Microsoft anticipó esta dificultad y creó una solución alternativa en lugar de dejar que los equipos improvisaran una. Publicaron @typescript/typescript6, un paquete de compatibilidad que incluye un ejecutable tsc6 y restablece el acceso a la interfaz de la API 6.0. Esto permite que el compilador antiguo y el nuevo coexistan sin que ninguno interfiera con el nombre binario del otro.

    La razón por la que es necesario este trabajo alternativo es que herramientas como typescript-eslint resuelven TypeScript por su nombre de paquete a través de una dependencia par. Por lo tanto, la solución recomendada es utilizar un alias de npm para redirigir ese nombre.

    La configuración completa del doble compilador se ve así:

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

    Con esto en su lugar, su linter, su transformador de pruebas y sus codemods siguen importando typescript como de costumbre y reciben de forma transparente la versión 6.0 en el fondo. Mientras tanto, al ejecutar npx tsc se utiliza la versión 7.0, por lo que sigue habiendo ventajas de velocidad donde más importan: en su editor y en los procesos de integración continua.

    Funciona, y hay que reconocerlo: se trata de una solución bien diseñada, explicada en el anuncio oficial y no algo que la comunidad tuvo que ingenierizar a la inversa.

    Aun así, se trata de dos instalaciones separadas del compilador que coexisten en un mismo node_modules, resueltas a través de un alias que cada nuevo miembro del equipo necesitará que le expliquen, además de una configuración que eventualmente habrá que modificar una vez que 7.1 esté realmente disponible. Llamémoslo como es: deuda técnica sin fecha de vencimiento establecida.

    La segunda trampa, para quienes saltaron por encima de 6.0

    Más allá de la API faltante, existe otro problema grave esperando a cualquier equipo que haya pasado directamente de una versión 5.x sin utilizar primero 6.0.

    TypeScript 7.0 adopta por completo los valores predeterminados introducidos en 6.0, y cada advertencia de obsoletad que surgió en 6.0 se convierte en un error grave en 7.0. Todo esto afecta de golpe:

    • strict está activo ahora por defecto.
    • module tiene como valor predeterminado ahora esnext.
  • rootDir tiene como valor por defecto ./ en lugar de inferirse automáticamente, por lo que si su tsconfig.json se encuentra fuera de la carpeta src, ahora debe establecerlo explícitamente; de lo contrario, el compilador interpretará incorrectamente la estructura de sus fuentes.
  • types utiliza un array vacío como valor por defecto en lugar de incluir todo. Si su código depende de variables globales provenientes de paquetes @types instalados, debe especificar el nombre de dichos paquetes o restaurar el comportamiento anterior con ["*"].
  • Varias opciones han sido eliminadas por completo en lugar de solo desaconsejarse: target: es5, downlevelIteration, moduleResolution: node, baseUrl, además de los modos de módulo amd, umd y systemjs. Utilizar cualquiera de ellas ahora genera un error de compilación, sin más.
  • Dentro de esa lista, el equipo destaca rootDir y types como los dos cambios que con mayor probabilidad tomarán por sorpresa a las personas, y eso coincide con lo que uno esperaría en la práctica. Ambos modos de fallo inunden tu terminal con errores que parecen indicar que el propio compilador está roto, en lugar de sugerir que “se ha modificado un valor predeterminado”. Esa es exactamente la clase de confusión que hace que se registre como un error del compilador en lugar de solucionarse con una simple edición en la configuración.

    También hay un cambio más sutil dirigido a quienes realizan manipulaciones de cadenas a nivel de tipo. La inferencia de tipos de literales de plantilla ahora considera un carácter como un emoji como una sola unidad, en lugar de dividirlo en sus dos unidades de código UTF-16. Ese es un modelo más intuitivo para la mayoría de los casos de uso, pero representa un cambio que rompe la compatibilidad con cualquier tipo auxiliar de estilo Length que contara intencionalmente unidades de código UTF-16 en lugar de caracteres visibles.

    La conclusión práctica: si aún estás en una versión 5.x, no pases directamente a 7.0. Primero prueba la versión 6.0. Esa versión intermedia existe específicamente para distribuir este conjunto de cambios que rompen la compatibilidad en dos actualizaciones menores, en lugar de imponerlos todos de golpe.

    Para quién realmente fue diseñada esta versión

    Este es el detalle que merece ser analizado con atención.

    Mire la lista de organizaciones que probaron TypeScript 7 antes de su disponibilidad general y proporcionaron comentarios sobre el anuncio: el equipo de VS Code, las propias aplicaciones Office, Teams, Power BI y los grupos de Loop y Xbox de Microsoft, además de Bloomberg, Canva, Figma, Google, Linear, Miro, Notion, Sentry, Slack y Vercel. Se trata de bases de código que cuentan con millones de líneas, respaldadas por equipos especializados en infraestructura de compilación, los cuales realizaron versiones preliminares durante meses y enviaron los problemas a los desarrolladores originales antes del lanzamiento.

    Para organizaciones de esa escala, este lanzamiento realmente cambia la forma en que se realiza el trabajo, y las cifras lo respaldan. El propio equipo de News Services de Microsoft informa que ahorra 400 horas al mes, tiempo que antes se dedicaba a esperar los procesos de integración continua. Cuando una sola verificación de tipo solía tomar siete minutos, reducir ese tiempo aproximadamente 8 veces transforma el ritmo diario de un ingeniero.

    Ahora compare eso con una startup de cinco personas que utiliza Nuxt con una configuración de lint que tiene en cuenta los tipos. Su verificación de tipos ya tardaba solo 9 segundos. La actualización les permite ahorrar unos 8 segundos, pero a cambio implica un pipeline de lint defectuoso, un verificador de plantillas Vue que simplemente no funciona, y una solución temporal mediante alias en package.json que el próximo ingeniero que se una al equipo tendrá que explicarles.

    La ventaja en velocidad aumenta según el tamaño de su base de código. Las complicaciones, en cambio, no varían en absoluto: son un costo fijo que se aplica tanto si su proyecto tiene diez archivos como diez millones.

    Nada de esto implica mala intención. Simplemente es lo que ocurre cuando un proyecto se optimiza en función de los comentarios que realmente puede observar. Las grandes bases de código empresariales estaban incluidas en el programa de prueba, por lo que sus problemas eran visibles y medibles mucho antes del lanzamiento. Los mantenedores del ecosistema —en su mayoría voluntarios que trabajaban en herramientas de análisis, integraciones con IDEs y herramientas de compilación— se encontraban al final del proceso de toma de decisiones sin tener voz en él, y lo único que recibían a cambio era un parche de compatibilidad y la promesa de que los problemas se resolverían en la versión 7.1.

    Una gran base de código convierte esta actualización en una ventaja inesperada. Una pequeña, en cambio, solo paga el mismo costo fijo por una recompensa mucho menor. Ese desequilibrio es toda la historia aquí.

    La verificación de preparación, a día de hoy

    Un mes después de la disponibilidad general, aquí está más o menos el estado actual de las cosas.

    Si está considerando hacer este cambio, la opción de menor riesgo es ejecutar 7.0 como una segunda tarea de verificación de tipos no bloqueante en CI, junto con la que ya tiene. Eso le proporcionará datos reales sobre los tiempos de ejecución y una mayor confianza, sin que 7.0 sea el elemento del que dependa realmente su proceso de compilación. Una vez que ambas tareas den resultado positivo durante aproximadamente una semana, podrá pasar a utilizar 7.0.

    Aquí no hay recompensa por ser uno de los primeros en adoptar una nueva versión, así que vale la pena conocer las opciones de ajuste disponibles: la bandera --checkers controla cuántos procesos de verificación de tipos se ejecutan en paralelo, con un valor predeterminado de 4. En un servidor CI con recursos limitados, es generalmente más sensato reducir ese valor a 1 o 2 procesos en lugar de mantener el valor predeterminado.

    Reproducir la interrupción en unos cinco minutos

    Nada de esto debe aceptarse sin verificar, y en efecto no debería ser así: el fallo es lo suficientemente pequeño y rápido como para provocarse deliberadamente en un proyecto de prueba desechable, antes de tocar algo que realmente importe.

    Comience con un scaffold fresco de Vite React-TypeScript, agregue una configuración de ESLint que tenga en cuenta los tipos, y luego intente forzar la instalación del compilador más reciente antes que este:

    npm create vite@latest ts7-probe -- --template react-ts
    cd ts7-probe
    npm install
    npm install -D typescript-eslint eslint
    npm install -D typescript@7
    

    La mayoría de las personas se topa con el problema justo en el momento de la instalación. El paquete published typescript-eslint declara un rango de dependencia par que establece como límite inferior la versión 6.1.0, por lo que npm rechaza directamente la resolución, mostrando un error ERESOLVE en lugar de una advertencia suave. De hecho, ese es el modo de fallo que permite más flexibilidad.

    El resultado más grave se produce si se ignora el conflicto y se fuerza la instalación de todos modos. Con los paquetes incompatibles en su lugar, al ejecutar lint se produce una caída dentro de typescript-estree mientras se construye el programa, debido a un acceso a una propiedad que ya no resuelve a nada:

    TypeError: Cannot read properties of undefined (reading 'Cjs')
        at .../@typescript-eslint/typescript-estree/dist/create-program/shared.js
    

    Fíjese en lo que ese mensaje no dice. Nunca menciona TypeScript 7, nunca indica una incompatibilidad de versiones, ni dice “configuración no compatible”. Se trata de una caída interna bruta; exactamente la misma queja planteada en el problema 12518: el informante solicitó un error de compatibilidad claro y legible para humanos en lugar de una traza de llamadas, y hasta el momento esa solicitud sigue pendiente.

    Ahora aplique la solución temporal con alias descrita anteriormente y ejecute nuevamente los mismos comandos. Lint funciona de nuevo, ya que comunica silenciosamente con TypeScript 6.0 en segundo plano, mientras que npx tsc por sí solo sigue utilizando la versión más rápida, 7.0.

    Mientras tenga su configuración de esta manera, vale la pena medir el tiempo que tarda en compilar bajo ambas versiones. Esa cifra, y no las pruebas de otros, es la que debe guiar su decisión; casi con certeza será mucho menos significativa que los resultados de VS Code, simplemente porque su código no tiene dos millones de líneas.

    Qué he aprendido

    Lo que hace que TypeScript 7 sea un caso peculiar es que existen dos interpretaciones contradictorias que son ambas correctas, y la mayoría de las pruebas solo han considerado una de ellas.

    Se trata de un trabajo importante en ingeniería de compiladores que devuelve horas reales cada semana a los equipos que las perdían debido a procesos de compilación lentos. También es una versión que incluyó solo la mitad de lo necesario, reveló ese hecho en lo más profundo del anuncio y dejó las consecuencias a cargo de los mantenedores, quienes no tenían voz en el calendario de lanzamientos.

    Lo que habría sido útil —y lo que no quedó claro en el lanzamiento— es una simple oración al principio: esta versión está lista para su pipeline de compilación, no para sus herramientas, y aquí está exactamente lo que eso significa para usted. Esa oración estaba técnicamente allí; simplemente estaba oculta varios párrafos después del gráfico de pruebas.

    La versión 7.1 está destinada a cerrar realmente esta brecha. Hasta que lo haga, el enfoque sensato es limitado: aprovechar la velocidad donde no cueste nada, ya sea en el editor o en CI, y dejar intactas todas las herramientas que aún importan directamente al compilador.

    Lecturas relacionadas

  • TypeScript 6 y 7: Inferencia más inteligente, luego una reescritura basada en Go — Aprenda cómo TypeScript 6 corrigió deficiencias clave en la inferencia y modernizó los valores predeterminados, sentando las bases para la reescritura total del compilador de TypeScript 7 en Go.