Compilaciones de TypeScript más rápidas con --isolatedDeclarations

Rate this content
Bookmark

La verificación de tipos en una base de código TypeScript puede ser lenta, especialmente para monorepos que contienen muchos proyectos que necesitan usar el verificador de tipos para generar archivos de declaración de tipos. En esta charla, presentamos, por primera vez, una nueva característica de TypeScript en la que estamos trabajando llamada “Declaraciones Aisladas” que permite que los archivos DTS se generen sin usar el verificador de tipos en absoluto. ¡Esto abre la puerta a una generación de declaraciones más rápida en TypeScript mismo, así como en herramientas externas escritas en otros lenguajes como ESBuild y swc. Verás cómo usar esta nueva opción, y tal vez (solo tal vez) te convencerás de los beneficios de los tipos de retorno explícitos. Lo más importante, mostraremos cómo las Declaraciones Aisladas permiten compilaciones paralelas para distribuir el trabajo a través de tus núcleos de CPU para mejorar significativamente la velocidad de compilación de tus proyectos TypeScript.

Titian-Cornel Cernicova-Dragomir
Titian-Cornel Cernicova-Dragomir
24 min
21 Sep, 2023

Comments

Sign in or register to post your comment.

Video Summary and Transcription

Esta charla discute los problemas de rendimiento en las compilaciones de TypeScript e introduce una nueva característica llamada declaraciones aisladas. Al ejecutar el compilador en paralelo y usar módulos aislados, se pueden lograr ganancias de rendimiento significativas. Las declaraciones aisladas mejoran la velocidad de compilación, la compatibilidad con otras herramientas y requieren que los desarrolladores escriban tipos en el código. Esta característica tiene el potencial de aumentar aún más el rendimiento y puede estar disponible en TypeScript pronto.

Available in English

1. Introducción a las Construcciones de TypeScript

Short description:

Hola a todos. Bienvenidos a mi charla, Acelerando las construcciones de TypeScript. Voy a hablar sobre el rendimiento de la construcción, especialmente en monorepos. Estamos desarrollando una próxima característica en colaboración con Bloomberg, Google y Microsoft. La motivación para esta característica son las quejas sobre el rendimiento de la construcción en TypeScript. Intentamos ejecutar el compilador en paralelo, lo que resultó en ganancias de rendimiento significativas para un monorepo de 23 proyectos.

Hola a todos. Bienvenidos a mi charla, Acelerando las construcciones de TypeScript. Mi nombre es Tiziano Cernico-Adragomir. Soy un ingeniero de software en Bloomberg en el equipo de infraestructura de TypeScript JavaScript, y también soy un colaborador del compilador de TypeScript.

Y hoy quiero hablar sobre el rendimiento de la construcción, especialmente el rendimiento de la construcción en monorepos. Y vamos a hablar sobre una próxima característica de TypeScript que hemos estado desarrollando en colaboración con Bloomberg, Google y Microsoft. Puedes echar un vistazo a esta característica en nuestro repositorio público de GitHub en nuestra bifurcación de TypeScript. Pero también vamos a hablar de ello hoy.

Entonces, ¿cuál es la motivación para esta característica? Bueno, si pasas cualquier cantidad de tiempo en Twitter, definitivamente encontrarás personas que se quejan sobre el rendimiento incorporado en TypeScript. Y estas quejas no son infundadas. Desafortunadamente, la comprobación de tipos puede ser lenta, especialmente si tienes mucho código en muchos proyectos en un monorepo. Entonces, la pregunta es, ¿qué podemos hacer al respecto? Bueno, podríamos optimizar el compilador, y el equipo de TypeScript definitivamente ha estado haciendo eso. Si revisas las notas de la versión para las últimas versiones, verás que cada versión trae nuevas optimizaciones al compilador. Y eso es un gran trabajo. También podríamos reescribir el compilador, y hay esfuerzos ahí fuera que están tratando de hacer esto. Estamos emocionados de ver a dónde van también. Pero intentamos un enfoque diferente. Pensamos en ejecutar las cosas en paralelo, porque mucho del hardware de hoy es multicore, la gente tiene muchos núcleos en sus escritorios y sus portátiles. Y sería genial si pudiéramos aprovechar esos para hacer las cosas más rápidas para las personas cuando construyen sus proyectos. Así que vamos a ejecutar el compilador en paralelo. Veamos qué ganancias de rendimiento podríamos obtener. Lo que hicimos en Silent Bloomer, tomamos uno de nuestros propios monorepos. Era un monorepo de 23 proyectos. Tiene más de 100,000 líneas de TypeScript código y un gráfico de dependencia muy profundo, así que puedes pensar en algo así, muchos proyectos con muchas dependencias. Y tratamos de ver qué ganancias podríamos obtener al ejecutar el comprobador de tipos en paralelo para este monorepo. Tomamos una línea de base inicial usando el soporte de proyecto compuesto incorporado de TypeScript, y obtuvimos tiempos de construcción de alrededor de 60 segundos a 30, dependiendo del hardware. Ahora, TypeScript-B, que es el soporte de proyecto compuesto en TypeScript, es de un solo hilo. No intentará construir nada en paralelo, por lo que todos estos proyectos se comprueban de tipo individualmente en orden de sus dependencias. Así que veamos qué podríamos hacer si intentamos ejecutar el compilador en paralelo. Lo que hicimos fue ejecutar una instancia separada del compilador para cada proyecto.

2. Optimizando el Paralelismo y la Gestión de Dependencias

Short description:

Agrupamos los proyectos en trabajadores con cachés compartidos. Sin embargo, los proyectos no son independientes, por lo que tenemos que esperar a que las dependencias terminen de construirse. Esto limita el paralelismo, permitiendo que solo se construyan simultáneamente unos pocos proyectos.

Ahora, no hicimos esto de una manera ingenua. Hubo algunas optimizaciones que sí hicimos. Por ejemplo, agrupamos todos los proyectos en varios trabajadores, y cada uno de estos trabajadores tenía una caché de archivos compartida y una caché compartida del árbol de sintaxis del archivo fuente, que ya son optimizaciones que TypeScript hace para su soporte de proyectos compuestos de todos modos. Así que solo estábamos tratando de emular eso.

Ahora, el problema con el que nos encontramos de inmediato es que los proyectos no son independientes. Así que no podemos simplemente ejecutar todo en paralelo. Necesitamos esperar a que las dependencias terminen de construirse. Entonces, por ejemplo, para el diagrama que mostré antes de las dependencias, obtendríamos una ejecución que se ve algo así. Y ya podemos ver que tenemos un gran límite en el paralelismo y solo hay dos proyectos que se ejecutan en paralelo al mismo tiempo. Así que solo dos proyectos se verifican en paralelo. E incluso en nuestro monorepo de muestra con 23 proyectos, solo conseguiríamos construir unos cuatro en paralelo.

3. Incrementando el Paralelismo y los Módulos Aislados

Short description:

En un portátil con 12 núcleos, solo utilizamos parte de la potencia de cálculo, dejando núcleos de CPU inactivos. Ejecutar cosas en paralelo resulta en una mejora del 10-20%, pero no es dramática. TypeScript realiza la comprobación de tipos, la emisión de declaraciones y la emisión de JavaScript para cada proyecto. Desbloquear la fase de comprobación de tipos de un proyecto requiere declaraciones disponibles de sus dependencias. Dependemos de la emisión de declaraciones aunque no elimine la necesidad de comprobación de tipos. El modo de módulos aislados de TypeScript permite la emisión de JavaScript sin dependencia de comprobación de tipos, convirtiéndolo en un proceso puramente sintáctico.

Ahora, ¿qué significa esto realmente? Por ejemplo, en un portátil con 12 núcleos, que es lo que vemos aquí en esta imagen, solo utilizamos parte de esa potencia de cálculo. Podemos ver que incluso mientras se ejecuta la construcción, hay mucha potencia de CPU que aún se deja sin utilizar. Muchos núcleos de CPU que simplemente están allí inactivos. Así que definitivamente no es un buen comienzo para ejecutar cosas en paralelo.

Veamos a veces qué tipo de mejoras podríamos obtener si hiciéramos esto? Y la respuesta es que definitivamente obtendremos mejoras, pero simplemente no son tan grandes. Quiero decir, hay una mejora de aproximadamente el 10-20% que obtenemos al ejecutar cosas en paralelo utilizando este enfoque, que es nuevamente mejor que lo que teníamos, pero no es algo que vaya a ser dramático.

Entonces, ¿cómo podemos aumentar el paralelismo disponible? ¿Cómo podemos ejecutar más cosas en paralelo? Bueno, para eso, primero necesitamos entender exactamente qué es lo que TypeScript realmente hace, y lo que hace son tres cosas. Realiza la comprobación de tipos, emite declaraciones, y emite JavaScript. Ahora, estas cosas no son perfectamente independientes, a saber, la emisión de declaraciones depende del resultado de la comprobación de tipos. Pero para cada uno de nuestros proyectos, TypeScript hará estas tres cosas. Así que, dentro de la construcción de cada uno de nuestros proyectos, estas tres cosas tienen que suceder.

Ahora, hay una idea clave aquí, a saber, que lo que se necesita para desbloquear un proyecto para iniciar su fase de comprobación de tipos es que necesita tener disponibles todas las declaraciones de sus dependencias. Así que, la emisión de declaraciones es lo que realmente se necesita para las dependencias. Realmente no nos importa si la dependencia ha terminado la comprobación de tipos si podemos obtener sus declaraciones. Así que, la cola de dependencias real se vería más como esto, ¿verdad? Cada fase de comprobación de tipos depende de la emisión de declaraciones de sus dependencias, no necesariamente de la comprobación de tipos. Eso es una idea interesante, pero mientras todavía tengamos esta dependencia entre la comprobación de tipos y la emisión de declaraciones, el hecho de que este sea el caso, el hecho de que dependamos de la emisión de declaraciones realmente no nos ayuda porque necesitamos hacer la comprobación de tipos de todos modos. Entonces, ¿podríamos eliminar esta dependencia? Bueno, para eso, deberíamos primero mirar por qué la emisión de JavaScript es tan independiente de la comprobación de tipos. ¿Cómo es eso? De hecho, incluso tenemos herramientas que emiten JavaScript sin la necesidad de un comprobador de tipos. Lo hacen completamente independientemente de TypeScript. ¿Cómo se permite esto? Bueno, hace unos años, TypeScript añadió un nuevo modo a TypeScript llamado módulos aislados. Entonces, ¿qué hace exactamente los módulos aislados? Bueno, asegura que cada archivo puede ser transpilado de TypeScript a JavaScript individualmente. Básicamente elimina cualquier dependencia en la comprobación de tipos de la emisión de JavaScript. Así que esto significa que la emisión de JavaScript se convierte en un proceso puramente sintáctico. Las herramientas todavía necesitan entender la sintaxis de TypeScript. Así que, cada vez que obtenemos una nueva sintaxis en TypeScript, todas las herramientas que emiten JavaScript necesitan entender esta nueva sintaxis. Pero la ventaja es que en realidad no necesitan entender todas las reglas semánticas de TypeScript. Solo necesitan entender la sintaxis lo suficiente como para poder eliminarla. Así que, básicamente, cuando hacemos la emisión de JavaScript, empezamos con un archivo de TypeScript, y lo que sucede dentro de un emisor de JavaScript es que todas las anotaciones de tipo son eliminadas, ¿verdad? Y este es un proceso muy simple. No es difícil construir tal transformación. Al menos no es difícil comparado con la construcción de un comprobador de tipos completo.

4. Eliminando la Dependencia y Declaraciones Aisladas

Short description:

Podemos eliminar la dependencia entre la emisión de declaraciones y la verificación de tipos al especificar todos los tipos en el archivo de TypeScript. Esto nos permitiría desbloquear las dependencias más rápido. TypeScript introduce la nueva característica llamada declaraciones aisladas, donde se agregan anotaciones de tipo a los valores que se incluyen en los archivos de declaración. El verificador de tipos no participa en la emisión de declaraciones para asegurar que siga siendo una transformación puramente sintáctica.

Entonces, ¿podríamos usar un enfoque similar para eliminar esta dependencia entre la emisión de declaraciones y la verificación de tipos? Para eso, tenemos que analizar un poco en qué consiste exactamente la emisión de declaraciones. En su mayor parte, también es un proceso de sustracción donde simplemente eliminamos cosas del archivo de TypeScript, excepto que ya no eliminamos los tipos. Estamos eliminando la implementación, por ejemplo, el cuerpo de la función, el cuerpo del constructor. Todo esto desaparece en los archivos de declaración.

Sin embargo, hay una excepción, en este caso, el tipo de retorno de esta función, porque si el desarrollador no especifica el tipo de retorno, la emisión de declaraciones debe acceder al verificador de tipos y averiguar cuál será el tipo de retorno de esta función. Y por eso se requiere la verificación de tipos para la emisión de declaraciones. Si todos escribieran todos los tipos en el archivo de TypeScript, en realidad no necesitaríamos el verificador de tipos para la emisión de declaraciones. Esta es una forma en la que podríamos eliminar la dependencia si especificamos todos los tipos, lo que nos permitiría desbloquear las dependencias más rápido.

Ya existen reglas de linting que podrían hacer cumplir esto, pero sería útil tener algo incorporado en la compilación real que garantice a otras herramientas qué anotaciones son necesarias. Por eso decidimos agregar una nueva bandera a TypeScript que llamamos declaraciones aisladas. Declaraciones aisladas es la nueva característica que estamos implementando. Veamos qué significa esta característica. Nuestra primera idea fue agregar anotaciones de tipo a todos los valores que se incluyen en los archivos de declaración. Esto se refiere principalmente a los valores exportados, aunque también hay algunas formas indirectas en las que los valores pueden incluirse en los archivos de declaración, incluso si no se exportan explícitamente.

Hicimos algunas excepciones. En algunos casos, los valores se pueden inferir fácilmente y tal vez podamos permitirlos sin tener anotaciones de tipo explícitas. Pero lo que es seguro es que el verificador de tipos en sí no puede participar en la emisión de declaraciones, porque queremos que la emisión de declaraciones sea puramente una transformación sintáctica donde simplemente eliminamos la implementación y no tenemos que acceder al verificador de tipos para obtener información de tipo del código fuente.

5. Anotación de Tipos e Inferencia

Short description:

No es necesario anotar todos los tipos a menos que optes por hacerlo. Si estás satisfecho con tus compilaciones de TypeScript, puedes mantener tu proyecto tal como está. Nuestra idea inicial era especificar anotaciones de tipo en todo, pero eso resultó ser difícil para proyectos grandes. Pasamos por tres fases de inferencia, pero encontramos problemas. Nuestro código requeriría anotaciones duplicadas para literales y objetos literales. Sin embargo, hicimos que la inferencia fuera más inteligente al inferir tipos para números y tipos literales, y al extraer información de la lista de parámetros para funciones.

Entonces, la siguiente pregunta lógica es, ¿tengo que anotar todos los tipos? Quiero señalar que no tienes que hacer nada a menos que optes por hacerlo. Si estás satisfecho con tus compilaciones de TypeScript, si estás satisfecho con la forma en que TypeScript fue y con tus tiempos de compilación, puedes mantener tu proyecto tal como está. Nadie te obliga a adoptar esto. Si tus dependencias adoptan esto, realmente no te importará porque solo estás consumiendo su archivo de declaración, por lo que no será algo en lo que todos tengan que optar.

Entonces, nuestra idea inicial, sin embargo, era que sí, necesitaríamos especificar anotaciones de tipo en todo. Resulta que esto hace que la conversión de proyectos grandes sea dolorosa y no es la mejor experiencia para los desarrolladores, especialmente al ver algunas de estas expresiones, podrías deducir fácilmente que sí, de hecho, el tipo de algo es un número. Pasamos por tres fases. Básicamente, la primera fue donde pensamos que no haríamos ninguna inferencia en este modo. La segunda fue donde pensamos que tal vez alguna inferencia trivial está bien. Y la última, que finalmente rechazamos, fue donde hacemos mucha más inferencia. Pero también nos encontramos con algunos problemas que veremos en unos momentos. Veamos cómo se vería nuestro código con cada una de estas versiones.

Entonces, sin inferencia. Lo que esto significaría es que tendrías que especificar tipos en absolutamente todo. Por ejemplo, estás asignando 20 a la variable margen. Es bastante obvio que el tipo debería ser número aquí, pero no permitimos ninguna anotación, por lo que tendrías que especificarlo. Tendrías que especificarlo para esta constante, básicamente duplicando el literal en ambos lugares, tanto en la posición del tipo como en el inicializador. Se vuelve aún peor para cosas como objetos literales, donde tienes que duplicar los nombres de las propiedades y los valores, y realmente se vuelve muy doloroso hacerlo. Para constantes que se inicializan con una función, bueno, tendrías que copiar la lista de parámetros nuevamente en la anotación de tipo, y también especificar el tipo de retorno. Y nuevamente, para campos, incluso si los estás inicializando con valores muy básicos, que debería ser obvio de qué tipo son, aún tendríamos que especificar el tipo explícitamente. Nuevamente, esto habría sido bastante doloroso y habría dificultado mucho que alguien realmente adopte esta característica. Así que decidimos hacer que nuestra declaración sea un poco más inteligente. Entonces, si vemos un literal de número, bueno, el tipo allí es obviamente número. Por lo que no necesitas especificarlo. Lo mismo para los tipos literales. Para los tipos de objeto, es un poco más complicado, pero no es imposible deducir el tipo a partir del inicializador. Así que decidimos que también podemos admitir esto. Para funciones que, para constantes que se inicializan con una función, bueno, no necesitas especificar toda la firma de la función como una anotación de tipo. Podemos extraer la mayor parte de la información que necesitamos de la lista de parámetros.

6. Inferencia Avanzada y Solución Rápida

Short description:

Deberás especificar el tipo de retorno. Para campos, puedes omitirlos si el inicializador es claro. El emisor de declaraciones de TypeScript es inteligente, pero queremos que sea simple y rápido. Podemos hacer más inferencia, pero no siempre será correcta. Las declaraciones tendrían que ser omitidas de manera optimista, lo que causaría problemas y complejidad. Añadir más inferencia podría degradar la experiencia del desarrollador. Para asegurar una adopción más fácil, hemos añadido una solución rápida.

Sin embargo, deberás especificar el tipo de retorno porque no queremos tener que entrar en el cuerpo de la función misma y buscar cualquier retorno e intentar sintetizar un tipo de retorno basado en eso. Y para los campos de función, y para los campos de clase, nuevamente, puedes simplemente omitirlos si el inicializador es lo suficientemente claro para que podamos inferir un tipo.

¿Qué pasa si queremos más, verdad? Estábamos muy emocionados por nuestro éxito inicial con esta forma trivial de inferencia, y decidimos, bueno, tal vez podamos hacer más. Tal vez podamos inferir más cosas. Y el problema es que el emisor de declaraciones de TypeScript es muy inteligente, y queremos que nuestros emisores sean simples y, con suerte, rápidos. Así que no queremos que el emisor de declaraciones, por ejemplo, tenga que buscar información en otros archivos. Así que pongamos un ejemplo. Digamos que tenemos una variable, y la estamos inicializando con el valor de otra variable. ¿Podríamos inferir trivialmente un tipo para orientation? ¿Qué tipo podríamos escribir en los archivos de declaración sin tener que involucrar al comprobador de tipos? Podríamos intentar usar typeOfHorizontal. Esto parece encajar muy bien. typeOf nos dará el tipo de la variable, y orientation debería tener el mismo tipo que lo que estamos asignando, ¿verdad? Bueno, a veces funciona. Por ejemplo, si horizontal está definido como una variable de tipo string, entonces sí, el tipo de horizontal será el mismo que el tipo de orientation porque ambos serán strings, y todo funcionaría muy bien. Sin embargo, si horizontal es una constante, entonces lo que realmente obtenemos para horizontal es el tipo literal horizontal. Entonces, ¿qué sucede cuando asignas esa variable a una variable mutable es que TypeScript realmente ampliará el tipo, por lo que orientation tendrá tipo string. Así que en este caso, el tipo de la variable horizontal será diferente que el tipo de la variable orientation porque tendremos básicamente string en un lado y horizontal en el otro lado. Así que no funciona en todos los casos. Entonces, ¿la respuesta es, podemos hacer más inferencia? La respuesta es sí, pero probablemente no siempre estaremos en lo correcto, por lo que las declaraciones tendrían que ser omitidas de manera optimista. Esto básicamente causa algunos problemas, sin embargo, porque lo que estamos diciendo aquí es que, bueno, un emisor de declaraciones podría producir declaraciones sin el comprobador de tipos, pero podrían estar equivocadas. Y luego TypeScript en sí podría regresar y generar un error al mirar toda la información en el sistema de tipos y decir, bueno, en este caso particular, si estás usando declaraciones aisladas y estás usando un emisor de declaraciones independiente, no podría haber sabido cuál era el tipo correcto allí. Así que esto es posible, pero crea un modelo mental muy complicado, lo que dificulta mucho la comprensión. Además, los errores serían mucho más difíciles de entender porque tendríamos que decirles a las personas por qué exactamente están teniendo un error en una cierta construcción. Y lo que obtuvimos fueron errores que sonaban algo como, este tipo que se infiere en las declaraciones aisladas es diferente de este otro tipo que se infiere normalmente por TypeScript. Y suena como si el compilador estuviera discutiendo consigo mismo. Las declaraciones aisladas son una cosa, el TSC normal dice otra cosa.

7. Mejorando la Experiencia del Desarrollador

Short description:

Agregar más inferencias que no siempre son correctas no es la mejor opción. Para asegurar una adopción más fácil, hemos añadido una solución rápida.

Y los desarrolladores involucrados básicamente no tienen participación en este proceso. Por lo tanto, todo esto podría resultar en degradar la experiencia del desarrollador en lugar de mejorarla, que fue la razón por la que queríamos más inferencia en primer lugar. Definitivamente, agregar más inferencias que no siempre son correctas no es la mejor opción.

Sin embargo, aún queríamos asegurarnos de que las personas tuvieran un tiempo más fácil adoptando esta característica. ¿Cómo podríamos asegurarlo? Bueno, decidimos agregar una solución rápida. La información ya está presente allí. Solo necesitamos insertar un tipo en nuestro código. Visual Studio Code ya tiene toda la información, el servicio de lenguaje que se ejecuta allí ya sabe cuáles son los tipos de todas las variables incluso si no están explícitos. Entonces, lo que podríamos hacer si hay una declaración aislada es simplemente usar una solución rápida para insertar el tipo sin tener que escribirlo nosotros mismos lo cual creo que definitivamente ayudará a todos los desarrolladores a adoptar esta característica.

8. Mejorando TypeScript con Declaraciones Aisladas

Short description:

Las declaraciones aisladas mejoran TypeScript de varias formas. Mejoran la velocidad y desbloquean más paralelismo al emitir las declaraciones de antemano. También mejoran la compatibilidad con otras herramientas y promueven la transparencia al requerir que los desarrolladores escriban tipos en el código.

Quiero enviar un agradecimiento especial a Hannah Jewell de Google que trabajó extensamente en esta característica y la mayor parte es gracias a ella.

Entonces, ¿cómo mejorarían las declaraciones aisladas a TypeScript? Bueno, esperamos mejorarla de varias formas. Con esta característica, en primer lugar, esperamos mejorar la velocidad, al pasar el verificador de tipos para sintetizar nuevos tipos probablemente mejorará la velocidad del límite de declaraciones por sí mismo. Esperamos desbloquear mucho más paralelismo. Si podemos emitir las declaraciones de antemano, los proyectos no necesitan esperar a que la fase de verificación de tipos de todas sus dependencias termine. Ya tienen las declaraciones y pueden realizar su propia verificación de tipos con eso. También esperamos mejorar la compatibilidad con otras herramientas. Como dije, ya existen herramientas que generan JavaScript a partir de TypeScript. Esperamos crear un ecosistema similar de herramientas que puedan emitir archivos de declaración sin el uso del verificador de tipos, pero que sean 100% compatibles con las declaraciones actuales de TypeScript. Y también esperamos mejorar la transparencia. A veces, los desarrolladores olvidan escribir tipos para sus valores exportados. Y a veces el verificador de tipos sintetiza algunas cosas que no son particularmente amigables para el desarrollador. Son tipos muy grandes o tipos sin ningún significado semántico, lo que resulta en una mala experiencia del desarrollador para los clientes de esas bibliotecas. Entonces, si las personas se ven obligadas a escribir estos tipos en el código, probablemente pensarán más en ellos y las declaraciones probablemente tendrán una mejor calidad solo por esto.

9. Mejorando el rendimiento con Declaraciones Aisladas

Short description:

Las declaraciones aisladas aumentan el paralelismo y mejoran el rendimiento de manera significativa. El futuro nos brinda la esperanza de obtener esta característica en TypeScript pronto, posiblemente en los próximos seis meses. Si bien no está claro si las declaraciones aisladas pueden ayudar en una configuración de proyecto único, existe el potencial de obtener un rendimiento aún más rápido con la posibilidad de un ecosistema de emisores de declaraciones de TypeScript. Agradecemos especialmente a todas las personas involucradas en el desarrollo de esta característica.

Pero volviendo a nuestro experimento de ejecutar la compilación de un monorepo en paralelo, vimos que sin declaraciones aisladas, había una cantidad limitada de paralelismo. Con las declaraciones aisladas, esperamos aumentar la cantidad de paralelismo disponible. Vimos que en la otra versión, esto era bastante limitado. En el mejor de los casos, dos proyectos podían verificar los tipos en paralelo en este ejemplo. Lo que queremos hacer es cargar todas las declaraciones de antemano, para desbloquear todos los proyectos lo más rápido posible. Queremos pasar de este diagrama a este diagrama. Con suerte, la diferencia entre estos dos es que esta vez no necesitaremos esperar a TypeScript porque la verificación de tipos se realizará mucho más rápido si podemos hacer todo esto en paralelo. Esa era la esperanza. Sin números reales, teóricamente esto podría funcionar. Pero en realidad no sabíamos qué tipo de mejoras de rendimiento estábamos viendo en proyectos reales.

Entonces, lo que hicimos fue convertir nuestro monorepo de muestra para usar declaraciones aisladas. Y tratamos de ver qué tipo de mejora de rendimiento obtendríamos al intentar compilar en paralelo con este nuevo enfoque de cargar todas las declaraciones de antemano. Así que, redoble de tambores, veamos los tiempos. Como puedes ver, incluso solo mirando los números, hay una gran mejora allí. Obtenemos tiempos de compilación de un solo dígito. Mirando un gráfico, tal vez se haga más claro que la mejora en el rendimiento es bastante dramática. Estamos hablando de una mejora de tres veces en el rendimiento. Cuando vimos estos números, realmente nos alegramos de que nuestra teoría funcionara y nuestras expectativas se cumplieran e incluso superaran en algunos aspectos.

Entonces, ¿qué nos depara el futuro? Bueno, esperamos obtener esta característica en TypeScript pronto. No sabemos exactamente cuándo, pero esperamos que suceda en los próximos seis meses. La otra pregunta que suelo recibir cuando hablo sobre esta característica es si esto puede ayudar en una configuración de proyecto único. Aún no estamos seguros de esto. Hemos realizado algunas experimentaciones, pero todavía hay algunas limitaciones que deben resolverse en el compilador de TypeScript primero. Veremos si podemos ayudar con eso también. ¿Puede esto volverse aún más rápido? Utilizamos la base del compilador de TypeScript para implementar nuestro propio emisor de declaraciones. Hay espacio para que otras herramientas sean mucho más rápidas, al igual que existe un ecosistema de emisores de JavaScript. Con suerte, habrá un ecosistema de emisores de declaraciones de TypeScript y eso hará que las cosas sean aún más rápidas.

Me gustaría agradecer a todas las personas involucradas de Google, Hannah Joo y Yann Kuehler, de Microsoft Daniel Rosenwasser, Jake Bailey y Ryan Kavanagh, y de Bloomberg, Rob Palmer, Thomas Chatwin y Ashley Claymore. También un agradecimiento especial al equipo de Flow, que implementó una característica muy similar hace un tiempo y que fue definitivamente una fuente de inspiración para nosotros. Muchas gracias por escuchar y estoy listo para responder cualquier pregunta en el chat. Gracias. Microsoft Mechanics www.microsoft.com www.microsoft.com www.facebook.com www.youtube.com

www.youtube.com

Check out more articles and videos

We constantly think of articles and videos that might spark Git people interest / skill us up or help building a stellar career

TypeScript and React: Secrets of a Happy Marriage
React Advanced Conference 2022React Advanced Conference 2022
21 min
TypeScript and React: Secrets of a Happy Marriage
Top Content
TypeScript and React are inseparable. What's the secret to their successful union? Quite a lot of surprisingly strange code. Learn why useRef always feels weird, how to wrangle generics in custom hooks, and how union types can transform your components.
React's Most Useful Types
React Day Berlin 2023React Day Berlin 2023
21 min
React's Most Useful Types
Top Content
We don't think of React as shipping its own types. But React's types are a core part of the framework - overseen by the React team, and co-ordinated with React's major releases.In this live coding talk, we'll look at all the types you've been missing out on. How do you get the props type from a component? How do you know what ref a component takes? Should you use React.FC? And what's the deal with JSX.Element?You'll walk away with a bunch of exciting ideas to take to your React applications, and hopefully a new appreciation for the wonders of React and TypeScript working together.
Stop Writing Your Routes
Vue.js London 2023Vue.js London 2023
30 min
Stop Writing Your Routes
The more you keep working on an application, the more complicated its routing becomes, and the easier it is to make a mistake. ""Was the route named users or was it user?"", ""Did it have an id param or was it userId?"". If only TypeScript could tell you what are the possible names and params. If only you didn't have to write a single route anymore and let a plugin do it for you. In this talk we will go through what it took to bring automatically typed routes for Vue Router.
Making Magic: Building a TypeScript-First Framework
TypeScript Congress 2023TypeScript Congress 2023
31 min
Making Magic: Building a TypeScript-First Framework
I'll dive into the internals of Nuxt to describe how we've built a TypeScript-first framework that is deeply integrated with the user's IDE and type checking setup to offer end-to-end full-stack type safety, hints for layouts, middleware and more, typed runtime configuration options and even typed routing. Plus, I'll highlight what I'm most excited about doing in the days to come and how TypeScript makes that possible not just for us but for any library author.
Full-stack & typesafe React (+Native) apps with tRPC.io
React Advanced Conference 2021React Advanced Conference 2021
6 min
Full-stack & typesafe React (+Native) apps with tRPC.io
Top Content
Why are we devs so obsessed with decoupling things that are coupled nature? tRPC is a library that replaces the need for GraphQL or REST for internal APIs. When using it, you simply write backend functions whose input and output shapes are instantly inferred in your frontend without any code generation; making writing API schemas a thing of the past. It's lightweight, not tied to React, HTTP-cacheable, and can be incrementally adopted. In this talk, I'll give a glimpse of the DX you can get from tRPC and how (and why) to get started.
How to properly handle URL slug changes in Next.js
TypeScript Congress 2022TypeScript Congress 2022
10 min
How to properly handle URL slug changes in Next.js
Top Content
If you're using a headless CMS for storing content, you also work with URL slugs, the last parts of any URL. The problem is, content editors are able to freely change the slugs which can cause 404 errors, lost page ranks, broken links, and in the end confused visitors on your site. In this talk, I will present a solution for keeping a history of URL slugs in the CMS and explain how to implement a proper redirect mechanism (using TypeScript!) for dynamically generated pages on a Next.js website.

Add to the talk notes: https://github.com/ondrabus/kontent-boilerplate-next-js-ts-congress-2022 

Workshops on related topic

React, TypeScript, and TDD
React Advanced Conference 2021React Advanced Conference 2021
174 min
React, TypeScript, and TDD
Top Content
Featured WorkshopFree
Paul Everitt
Paul Everitt
ReactJS is wildly popular and thus wildly supported. TypeScript is increasingly popular, and thus increasingly supported.

The two together? Not as much. Given that they both change quickly, it's hard to find accurate learning materials.

React+TypeScript, with JetBrains IDEs? That three-part combination is the topic of this series. We'll show a little about a lot. Meaning, the key steps to getting productive, in the IDE, for React projects using TypeScript. Along the way we'll show test-driven development and emphasize tips-and-tricks in the IDE.
Best Practices and Advanced TypeScript Tips for React Developers
React Advanced Conference 2022React Advanced Conference 2022
148 min
Best Practices and Advanced TypeScript Tips for React Developers
Top Content
Featured Workshop
Maurice de Beijer
Maurice de Beijer
Are you a React developer trying to get the most benefits from TypeScript? Then this is the workshop for you.In this interactive workshop, we will start at the basics and examine the pros and cons of different ways you can declare React components using TypeScript. After that we will move to more advanced concepts where we will go beyond the strict setting of TypeScript. You will learn when to use types like any, unknown and never. We will explore the use of type predicates, guards and exhaustive checking. You will learn about the built-in mapped types as well as how to create your own new type map utilities. And we will start programming in the TypeScript type system using conditional types and type inferring.
Deep TypeScript Tips & Tricks
Node Congress 2024Node Congress 2024
83 min
Deep TypeScript Tips & Tricks
Top Content
Workshop
Josh Goldberg
Josh Goldberg
TypeScript has a powerful type system with all sorts of fancy features for representing wild and wacky JavaScript states. But the syntax to do so isn't always straightforward, and the error messages aren't always precise in telling you what's wrong. Let's dive into how many of TypeScript's more powerful features really work, what kinds of real-world problems they solve, and how to wrestle the type system into submission so you can write truly excellent TypeScript code.
Practice TypeScript Techniques Building React Server Components App
TypeScript Congress 2023TypeScript Congress 2023
131 min
Practice TypeScript Techniques Building React Server Components App
Workshop
Maurice de Beijer
Maurice de Beijer
In this hands-on workshop, Maurice will personally guide you through a series of exercises designed to empower you with a deep understanding of React Server Components and the power of TypeScript. Discover how to optimize your applications, improve performance, and unlock new possibilities.
 
During the workshop, you will:
- Maximize code maintainability and scalability with advanced TypeScript practices
- Unleash the performance benefits of React Server Components, surpassing traditional approaches
- Turbocharge your TypeScript with the power of Mapped Types
- Make your TypeScript types more secure with Opaque Types
- Explore the power of Template Literal Types when using Mapped Types
 
Maurice will virtually be by your side, offering comprehensive guidance and answering your questions as you navigate each exercise. By the end of the workshop, you'll have mastered React Server Components, armed with a newfound arsenal of TypeScript knowledge to supercharge your React applications.
 
Don't miss this opportunity to elevate your React expertise to new heights. Join our workshop and unlock the potential of React Server Components with TypeScript. Your apps will thank you.
Advanced TypeScript types for fun and reliability
TypeScript Congress 2022TypeScript Congress 2022
116 min
Advanced TypeScript types for fun and reliability
Workshop
Maurice de Beijer
Maurice de Beijer
If you're looking to get the most out of TypeScript, this workshop is for you! In this interactive workshop, we will explore the use of advanced types to improve the safety and predictability of your TypeScript code. You will learn when to use types like unknown or never. We will explore the use of type predicates, guards and exhaustive checking to make your TypeScript code more reliable both at compile and run-time. You will learn about the built-in mapped types as well as how to create your own new type map utilities. And we will start programming in the TypeScript type system using conditional types and type inferring.
Are you familiar with the basics of TypeScript and want to dive deeper? Then please join me with your laptop in this advanced and interactive workshop to learn all these topics and more.
You can find the slides, with links, here: http://theproblemsolver.nl/docs/ts-advanced-workshop.pdf
And the repository we will be using is here: https://github.com/mauricedb/ts-advanced
Mastering Node.js Test Runner
TestJS Summit 2023TestJS Summit 2023
78 min
Mastering Node.js Test Runner
Workshop
Marco Ippolito
Marco Ippolito
Node.js test runner is modern, fast, and doesn't require additional libraries, but understanding and using it well can be tricky. You will learn how to use Node.js test runner to its full potential. We'll show you how it compares to other tools, how to set it up, and how to run your tests effectively. During the workshop, we'll do exercises to help you get comfortable with filtering, using native assertions, running tests in parallel, using CLI, and more. We'll also talk about working with TypeScript, making custom reports, and code coverage.