Pruebas de rendimiento del compilador Go de TypeScript 7 en una aplicación real de Next.js.
Una comparación práctica de los tiempos de verificación con tsc entre TypeScript 6 y 7 en una base de código real de Next.js, que incluye un error por discrepancia en CI y orientación para la actualización.
Mis mismos 412 archivos, verificados dos veces con dos versiones diferentes del compilador. Con TypeScript 6, la comprobación tomó 3.8 segundos. Con TypeScript 7, tardó 0.41 segundos. El verificador de tipos que realiza el trabajo es funcionalmente el mismo en el fondo.
La cifra publicada por Microsoft indica una aceleración de 8 a 12 veces medida en VS Code. Lo que realmente importa aquí es lo que reporta tsc --extendedDiagnostics en un repositorio determinado. Un trabajo de CI que antes se detenía por un paso fallido en la generación con Prisma no se vuelve de repente diez veces más rápido en general solo porque el verificador de tipos se aceleró; solo esa etapa se vuelve más rápida. Todo lo demás en la cadena de procesamiento sigue siendo tan lento como antes.
Abra una terminal.
Omita next dev. Vaya directamente al verificador en sí, ejecútelo desde la raíz de la aplicación:
pnpm exec tsc --noEmit --extendedDiagnostics
Tenga en cuenta el valor de Check time que muestra. Esa única línea es la única medida que merece ser registrada aquí hasta el final.
Microsoft lanzó TypeScript 7.0 el 8 de julio de 2026. El sistema de tipos en sí no cambió, y el binario del compilador sigue llamándose tsc, pero internamente ahora es una versión del compilador en Go. La tabla del anuncio de la versión 1.0 muestra que el tiempo de verificación en VS Code disminuyó de 125.7 segundos a 10.6 segundos. Esa cifra corresponde al propio códigobase de Microsoft, no a un proyecto típico de Next.js.
Lo que realmente es útil es el número equivalente para una aplicación pequeña de Next.js con cuatro rutas que ya ha sido probada en todos los demás aspectos, además del número correspondiente: cuánto cuesta ejecutar next build una vez que el verificador subyacente es el nuevo. Igualmente importante es documentar el tipo de error que surge cuando una solicitud de integración automática asume que “más rápido” y “se comporta de manera diferente” significan lo mismo.
La prueba continua de la tarde mintió sobre un error de tipo
Imaginen un equipo que actualizó la dependencia typescript a la versión 7 en una aplicación de facturación el martes, porque un artículo de blog prometía una aceleración 10 veces mayor. La prueba continua pasó a estado verde notablemente más rápido. Alentados por esto, un revisor aprobó e integró una función auxiliar branded-id que, como resultó, no realizaba la verificación de tipos en la máquina local de un compañero del equipo.
El helper se compiló sin problemas en CI solo porque CI aún resolvía la versión 6 de typescript a través de una dependencia del espacio de trabajo raíz. Mientras tanto, la máquina local tenía instalada directamente la versión 7. El propio sistema de tipos no había cambiado; ese es precisamente el punto de la afirmación de Microsoft. Sin embargo, tsconfig en CI fijaba typescript a un alias de paquete, @typescript/typescript6, que quedó tras una entrada de sobrescritura añadida durante el período de prueba y que nunca se eliminó.
Así que el verdadero problema no era que TypeScript 7 se comportara de manera diferente. Se trataba de dos binarios del compilador distintos, una situación inconsistente en el archivo de lockfile y un mensaje en Slack que afirmaba que “7 ya está instalado” cuando, claramente, no era así, al menos no en todas partes.
Aquí está la forma que tomó en la práctica: una solicitud de integración titulada “Eliminar los castings as InvoiceId; 7 es más estricto”. En realidad, TypeScript 7 no era más estricto en este caso. El mismo commit también activó la bandera del compilador erasableSyntaxOnly, lo cual representa un cambio de política completamente distinto y que será objeto de discusión por separado más adelante. Combinar una mejora puramente de rendimiento con un cambio en la política de comportamiento es precisamente cómo surgen estos mitos.
La solución consiste en dividir dicho commit en dos partes: el simple aumento de versión y el cambio de política por separado. Solo así las mediciones de tiempo tienen sentido.
La frase que Microsoft publicó realmente
En el anuncio oficial de TypeScript 7.0 del 8 de julio de 2026, Daniel Rosenwasser describió esta versión como una que introduce la ejecución de código nativo, el procesamiento multihilo a través de memoria compartida y un conjunto de optimizaciones que, en general, logran aceleraciones entre 8 y 12 veces en las compilaciones completas.
La parte de ese anuncio que la mayoría de las personas pasa por alto es la frase sobre el hecho de que el sistema de tipos permanece sin cambios.
Según el anuncio, la nueva implementación basada en Go fue transferida de la implementación existente a través de un cuidadoso proceso de porteo en lugar de ser reconstruida desde cero, y su comportamiento de verificación de tipos es estructuralmente similar al de TypeScript 6.0.
No hay nueva sintaxis en ninguna parte de esta actualización. Lo que cambió es la velocidad de ejecución bruta para la misma lógica subyacente. Si los errores de tipo cambian después de actualizar la versión, eso no es un comportamiento esperado; se trata de un error que merece ser reportado.
Next.js 16.3 incluyó documentación que indica que next build utilizará TypeScript 7 para su paso de verificación de tipos si el proyecto tiene TypeScript 7 instalado como dependencia directa. Eso proporciona un segundo punto para medir el tiempo, además de la ejecución independiente de tsc.
Los dos temporizadores que realmente utilicé
Se utilizó la misma aplicación de prueba en todo momento: Next.js 16.3, React 19, cuatro rutas, la tabla de facturas, y la opción del compilador desactivada en esta sesión para que las cifras no se mezclaran.
Temporizador uno: tsc --noEmit --extendedDiagnostics. Temporizador dos: next build, observando la línea de verificación de tipos en su salida.
Agregué TypeScript 7 al proyecto como dependencia.
pnpm add -D typescript@7
El ejecutable sigue llamándose tsc. Durante la fase de previsualización, el paquete se conocía como @typescript/native-preview y su binario se llamaba tsgo. Ese nombre ya no se utiliza ahora que esta es la versión estable. Si encuentras algún contenido o tema que siga haciendo referencia a tsgo, se refiere al período de previsualización, no a la herramienta actual.
Para permitir que ambas versiones principales coexistan en el disco, Microsoft publicó un paquete complementario, @typescript/typescript6. Este expone un binario tsc6, lo que significa que la orden regular tsc puede apuntar a la versión 7 sin abandonar los equipos o herramientas que aún dependen de la versión 6.
pnpm add -D @typescript/typescript6
A partir de ahí, se puede utilizar el mismo tsconfig.json para ambas:
pnpm exec tsc6 --noEmit --extendedDiagnostics
pnpm exec tsc --noEmit --extendedDiagnostics
Mismos archivos de origen. Mismo parámetro strict. Mismos alias de rutas que generó Next.js al crear el proyecto con create-next-app.
Cada comando se ejecutó tres veces, y la primera ejecución se descartó, ya que una caché del sistema de archivos no representa una verificación inicial realista.
Cómo eran las cifras en esta base de código
La aplicación de pruebas tiene cuatro rutas y aproximadamente 80 archivos en TypeScript que pertenecen al propio proyecto, además de los archivos que genera automáticamente Next.js.
Ejecutando TypeScript 6.0 mediante tsc6, tomando la mediana de las dos ejecuciones conservadas:
- Archivos verificados: 412
- Tiempo de verificación: 3.82 segundos
- Tiempo total: 4.25 segundos
Ejecutando TypeScript 7.0 mediante tsc, con la misma configuración:
- Archivos verificados: 412
- Tiempo de verificación: 0.41 segundos
Eso representa una mejora de aproximadamente 9 veces en el tiempo de verificación específicamente. No 12 veces, ni siquiera cerca de la reducción de 125 segundos a 10 segundos que a veces se menciona en escenarios de VS Code. Esto es simplemente lo que produjo este repositorio en particular.
Al observar el paso de verificación de tipos dentro de next build:
- En la versión 6: 5.1 segundos
- En la versión 7: 1.4 segundos
Todo lo demás en next build —empaquetado y generación estática en las cuatro rutas— se mantuvo más o menos estable. Si su pipeline de CI ejecuta lint, luego verificación de tipos, después compilación y finalmente pruebas end-to-end, la parte de verificación de tipos disminuyó notablemente, pero la parte de pruebas end-to-end no ofreció mejoras significativas.
Un segundo proyecto, repleto de esquemas Zod y con unos 300 archivos de lógica y controladores de validación, mostró un aumento aún mayor:
- Tiempo de verificación de la versión 6: 11.4 segundos
- Tiempo de verificación de la versión 7: 1.3 segundos
Parece que un código con más tipos genera una mejora relativa mayor. Un pequeño sitio de marketing con una docena de archivos no mostraría ni siquiera cerca de una aceleración 10 veces mayor, simplemente porque apenas hay contenido para que el verificador lo analice.
El error que surgió después de la actualización
No se trató de un cambio en el comportamiento de la verificación de tipos, sino de un problema con las herramientas utilizadas.
eslint-plugin-react-hooks seguía iniciando typescript a través de la configuración parserOptions.project. Eso funcionaba bien en la versión 7, pero dejó de funcionar durante los meses previos a la versión preliminar de tsgo. Un bloque parserOptions obsoleto seguía apuntando a un archivo tsconfig.eslint.json separado, el cual establecía "compilerOptions": { "strict": false } específicamente para evitar que las pruebas antiguas generaran errores.
CI utilizaba esa configuración simplificada para la verificación de código, mientras que tsc empleaba la configuración real del proyecto. Dos fuentes de verdad diferentes. Como resultado, existía una discrepancia relacionada con noImplicitAny que pasó desapercibida dentro de una herramienta de pruebas, invisible para el analizador de código. Una vez que la versión 7 hizo que ejecutar tsc fuera lo suficientemente rápido como para hacerlo constantemente, agregué tsc --noEmit directamente a las verificaciones de los pull requests y eliminé por completo la configuración de TypeScript basada únicamente en ESLint.
{
"scripts": {
"typecheck": "tsc --noEmit",
"lint": "biome check .",
"ci": "pnpm typecheck && pnpm lint && pnpm test && pnpm build"
}
}
La solución real no fue nada espectacular. Lo que se contaba era que “la versión 7 dañó nuestros tipos”. Pero eso no fue cierto; la configuración duplicada sí lo causó.
Verificar qué está realmente ejecutándose en su sistema
Antes de confiar en cualquier número, confirme qué binario está realizando el trabajo.
pnpm exec tsc -v
Está buscando Version 7.x en el resultado. Si sigue indicando 5 o 6, su espacio de trabajo está utilizando una copia obsoleta proveniente de algún lugar. En un monorepo con pnpm, which lo dirigirá al lugar incorrecto. pnpm exec, en cambio, no lo hará.
Ejecute los diagnósticos tres veces por separado y descarte el primer resultado.
pnpm exec tsc --noEmit --extendedDiagnostics
Los campos a los que debe prestar atención en ese resultado son: la cantidad de archivos procesados, qué proporción proviene del código de las bibliotecas, cuánta proviene de las definiciones de tipo, cuánto corresponde a su propio código fuente, además de la duración de la verificación y la duración total.
Ahora instale la versión 6 junto con la versión 7 y diríjala al mismo conjunto de archivos.
pnpm add -D @typescript/typescript6
pnpm exec tsc6 --noEmit --extendedDiagnostics
Si la duración de las verificaciones no disminuye en un múltiplo significativo en un código con cientos de archivos, o bien no se está utilizando realmente la versión 7, o bien la muestra es demasiado pequeña: una docena de archivos no le mostrarán nada.
También vale la pena ejecutar next build dos veces, una vez contra cada binario, y registrar solo la línea de verificación de tipos en cada ocasión. No incluya toda la duración de la compilación en un análisis sobre la velocidad de TypeScript; Turbopack es un sistema separado que realiza tareas distintas.
Si se encuentra un error de tipo que aparece en la versión 7 pero no en la versión 6, con un tsconfig idéntico, infórmelo. Eso está fuera del alcance de lo que se discute aquí. La propia declaración de Microsoft es que la lógica de verificación no ha cambiado estructuralmente, por lo que una discrepancia como esa es un error, y no algo que deba considerarse como un costo esperado de la migración.
De dónde proviene realmente la velocidad
La mejora se debe al propio verificador. El análisis y el enlazado también se aceleraron, pero la duración de la verificación es el valor que aparece en los registros de CI y que realmente perciben las personas.
La respuesta del editor es otra historia: se trata del servicio de lenguaje, no del compilador independiente. En la tabla de facturas, las acciones de navegación como ir a la definición parecieron subjetivamente más rápidas. No se registró el tiempo de cada tecla, por lo que no hay una tabla con valores en milisegundos que ofrecer aquí.
next dev y su ciclo de Fast Refresh no se aceleraron significativamente con este cambio, ya que Fast Refresh nunca estuvo bloqueado durante una ejecución completa de tsc en primer lugar.
Esto realmente da sus frutos con agentes o bucles automatizados que ejecutan tsc --noEmit después de cada archivo que modifican. El bucle ahora se completa lo suficientemente rápido como para que omitir la verificación deje de ser una vía rápida tentadora. Ese es el beneficio real, aunque no se anuncie. El mismo agente que aún escribe enums simples en lugar de objetos as const ahora recibe la información al respecto con mayor rapidez.
Cálculo del costo real
Instalación: un aumento en una dependencia, además de eliminar un script tsgo sobrante que ya no era necesario.
Efecto en CI: en la aplicación principal, el paso de verificación de tipos pasó de 3.8 segundos a 0.4 segundos; en el árbol de workers, bajó de 11.4 segundos a 1.3 segundos. Los más de ocho minutos restantes del pipeline no se vieron afectados.
Costo de los rumores: una solicitud de integración culpó a la versión 7 por una regresión que en realidad fue causada por un cambio en una bandera incluido en el mismo commit. Mantenga esos commits separados.
Experiencia del editor: una mejora agradable, pero no tanto como para cuantificarla con un número en los comentarios.
Nomenclatura: tsc ahora se refiere a la versión 7, y tsc6 es su alternativa. Si ambos binarios están en su PATH, documente esto claramente en el README para que nadie se confunda más adelante.
¿Debería actualizar a 7 o quedarse en 6?
Pase a la versión 7. El comportamiento de verificación de tipos es el mismo motor, solo que funciona más rápido; no hay nueva sintaxis que aprender adicionalmente.
Solo manténgase en la versión 6 si existe un plugin específico, uno al que pueda darle nombre, que aún no haya añadido soporte para la versión 7. Escriba el nombre de ese plugin directamente en su referencia de versión. “Esperar a que las cosas se estabilicen” no es una razón válida por sí sola.
No incluya la actualización a la versión 7 junto con un cambio de erasableSyntaxOnly en la misma solicitud de integración: si algo falla, no podrá determinar qué cambio lo causó.
Tampoco elimine la opción tsc --noEmit de su pipeline de CI solo porque la versión 7 lo hace más rápido. La velocidad es la razón para mantener esa opción, no una razón para eliminarla.
Los límites reales de esta comparación
La reducción de 3.82 s a 0.41 s se aplica a esta aplicación específica con cuatro rutas. La disminución de 11.4 s a 1.3 s provino de un códigobase distinto centrado en workers. La mejora de 8 a 12 veces que menciona Microsoft se refiere a compilaciones completas en repositorios del tamaño de VS Code. Nadie volvió a ejecutar VS Code aquí.
La frase “estructuralmente idéntico”, con fecha del 8 de julio de 2026, proviene directamente del propio anuncio de Microsoft. Si los errores que reporta su proyecto realmente cambian después de la actualización, considérelo un defecto que debe registrarse, y no algún efecto secundario extraño que pueda ignorarse.
No hay forma de inspeccionar desde aquí el proceso de elevación de dependencias. Si pnpm exec tsc -v muestra una versión principal localmente mientras que los registros de CI muestran otra diferente, en realidad aún no ha validado TypeScript 7; lo que tiene es un problema de resolución de PATH disfrazado de comparación de versiones.
Ejecuta tanto tsc6 como tsc tres veces cada uno. Registra el tiempo de verificación y la cantidad de archivos en cada ejecución. Esos cuatro números constituyen el conjunto de datos bruto que puedes compartir si deseas recibir comentarios sobre tu configuración específica.
Reproducción mínima para una carpeta de prueba
Si prefieres no tocar tu aplicación real por el momento, aquí tienes el par de instalaciones más pequeño posible que sigue demostrando el problema del “hoisting”.
mkdir ts7-lab && cd ts7-lab
pnpm init
pnpm add -D typescript@7 @typescript/typescript6
echo '{ "compilerOptions": { "strict": true, "noEmit": true } }' > tsconfig.json
echo 'export type InvoiceId = string; export const n: InvoiceId = "inv_1";' > index.ts
pnpm exec tsc -v
pnpm exec tsc6 -v
pnpm exec tsc --extendedDiagnostics
pnpm exec tsc6 --extendedDiagnostics
Anota las cadenas de versión y los tiempos de verificación para ambos. Luego agrega un paquete de espacio de trabajo que siga indicando typescript@6 como dependencia, y observa lo que muestra pnpm exec tsc -v desde la raíz del repositorio. Esa discrepancia es exactamente el tipo de sorpresa que puede presentarte CI.
En el proyecto de facturas, otro aspecto importante que vale la pena registrar es si next build realmente imprime una línea Finished TypeScript proveniente de la versión 7. Si esa línea nunca aparece, significa que Next.js está utilizando un verificador de tipos distinto al que invoca tu script typecheck. Es necesario sincronizar estos dos herramientas; ejecutar dos verificadores diferentes al mismo tiempo fue precisamente cómo se coló el error de branded-id en las pruebas anteriores.
Una verificación rápida de un minuto para los revisores: abre app/invoices/page.tsx, pasa el cursor sobre un tipo de searchParams y espera a que aparezca la información en el tooltip. Repite el proceso tanto en la versión 6 como en la versión 7. Esta verificación no requiere cronómetro; lo importante es que el texto que aparece al pasar el cursor no cambió entre las versiones. El mismo comportamiento, pero con un motor más rápido en la versión 7.
Si su proyecto mantiene un archivo tsconfig.eslint.json separado con configuraciones más flexibles, deshágase de él la misma semana que realice la actualización. Un verificador de tipos sencillo elimina la excusa para que lint utilice reglas diferentes a las del proceso de compilación.
Una medida que vale la pena registrar desde el primer día: ejecute tsc --noEmit --pretty false 2>&1 seguido de wc -l, antes y después de la actualización. La cantidad de errores debe ser exactamente la misma en ambos casos. En la aplicación de facturas fueron cero en ambos momentos. En el proyecto worker-tree también fueron cuatro en cada ocasión: los mismos archivos y los mismos mensajes en ambas situaciones. Esa igualdad resume realmente toda la historia de la migración. Si las cantidades no coinciden, deje de repetir ese eslogan sobre el enfoque 10x y comience a comparar directamente los dos registros de salida.
Mantenga ambos registros guardados como /tmp/tsc6.txt y /tmp/tsc7.txt durante aproximadamente una semana después de cada actualización. Úselos una vez que todo esté establecido, pero no en la noche en que envíe realmente la actualización.
Guía para quien herede este código en el futuro
Exija que en el modelo de solicitud de integración aparezca la salida de pnpm exec tsc -v. Si no indica 7, significa que la mejora de rendimiento nunca se implementó realmente.
No combine esta actualización con erasableSyntaxOnly, verbatimModuleSyntax ni con una limpieza más amplia de tsconfig en la misma modificación. Esos cambios corresponden a una etapa posterior; esta se refiere únicamente a un compilador más rápido que realiza la misma tarea.
Sigua ejecutando tsc --noEmit en CI, aunque ahora cueste casi nada. Precisamente ese bajo costo es el motivo para mantenerlo activo.
Sesión de laboratorio, grabada en vivo: comandos y resultados
Esta sección documenta el mismo laboratorio de facturación con cuatro rutas utilizado en toda esta serie. Las versiones fijadas antes de comenzar son: Node 24, TypeScript 7, Next 16.3.
Estos pasos se encuentran en notes/lab.md del repositorio para que una sesión futura no dependa de la memoria. Puede copiarlos en secuencia.
node -v
pnpm exec tsc -v
pnpm exec next --version
Anote los tres números de versión en la parte superior de su nota. Si alguna versión principal no coincide con lo que cree que está utilizando, deténgase allí; todo lo que venga después generará resultados engañosos de manera más sutil.
A continuación viene el recorrido por las rutas:
pnpm exec next dev
Visite /, /invoices, /invoices/1, /settings, y luego nuevamente /invoices. Active la opción “Preservar registro” en DevTools. Tome una captura de pantalla tanto del cuadro de filtros como de la barra de direcciones. Esa combinación resulta ser el dato más útil en más de estas verificaciones de lo esperado.
Luego ejecute el comprobador de tipos:
pnpm exec tsc --noEmit --pretty false
echo $?
Un código de salida cero no es el resultado final; simplemente es la señal para pasar a verificar el comportamiento en tiempo de ejecución.
Finalmente, lo que realmente importa en todo esto: ejecute los comandos ya enumerados bajo “Cómo verlo en su máquina”. No los omita solo porque ya ha visto números aquí; su máquina no es la fuente de esos números. El calor ambiental, una laptop de 16 GB y lo que sea que Chrome esté haciendo en segundo plano afectarán más los tiempos de RSS, verificación de hora y cancelación de solicitudes que cualquier pequeño cambio en el framework.
Otra costumbre útil de mantener: una sola línea que indique un “arreglo fallido” en la nota; una oración, algo como “Probé X, pero aún se observó Y”. Esa línea es lo que mantiene este registro como un documento funcional y no como una presentación pulida. Un seguimiento útil incluye una lista de versiones, el comando exacto, la salida y el arreglo fallido. Una captura de pantalla del panel de control no lo es.
Lecturas relacionadas
- El compilador de TypeScript en Go y la ejecución nativa: una guía de migración — Aprenda cómo el compilador basado en Go de TypeScript y la ejecución nativa de Node.js afectarán los proyectos React y Next.js, y qué debe corregir en su tsconfig ahora mismo.
- Dentro de la reescritura en Go de TypeScript 7: mejoras de rendimiento sin cambios en el código — Aprenda cómo el compilador basado en Go de TypeScript 7 permite compilaciones 8-12 veces más rápidas, por qué funciona este cambio de arquitectura y cómo actualizar de forma segura los proyectos existentes.