5 points par GN⁺ 2024-05-05 | 1 commentaires | Partager sur WhatsApp
  • Figma a migré l’ensemble de son code Skew, son langage maison utilisé pour le rendu mobile et le visualiseur de prototypes, vers TypeScript après avoir atteint les limites de Skew en matière d’onboarding, d’intégration et d’écosystème
  • Les conditions de cette transition ont été réunies grâce à l’élargissement du support de WebAssembly dans les navigateurs mobiles, au remplacement du moteur sur les chemins critiques par un moteur C++, et à la croissance des équipes prototypage et mobile
  • La migration s’est déroulée en trois phases : Write Skew, build SkewWrite Skew, build TypeScriptWrite TypeScript, build TypeScript, avec un transpileur Skew-vers-TypeScript permettant de préserver le flux de développement
  • Le processus a révélé des problèmes de compatibilité liés aux performances de la déstructuration de tableaux, aux différences de devirtualization (suppression des appels virtuels), à l’ordre d’initialisation, au raccordement des source maps et à l’absence de compilation conditionnelle
  • Au final, Figma a obtenu une base de code TypeScript passant les tests unitaires et offrant des performances proches de celles de Skew, et considère désormais comme prochaines étapes l’intégration du code interne et externe, la gestion des packages et l’exploitation de l’écosystème TypeScript

Pourquoi passer de Skew à TypeScript

  • Skew est né d’un projet annexe au début de Figma et répondait au besoin de créer rapidement un visualiseur de prototypes compatible web et mobile
  • En évoluant vers un langage compilé en JavaScript, il offrait des optimisations avancées et des temps de compilation rapides, mais son coût de maintenance a augmenté à mesure que le code du visualiseur de prototypes s’est accumulé
    • difficile à apprendre pour les nouvelles recrues
    • pas facilement intégrable au reste de la base de code
    • absence d’un écosystème développeur en dehors de Figma
  • Les bénéfices attendus du passage à TypeScript concernaient surtout la vitesse de développement et l’élargissement de la collaboration
    • simplification de l’intégration du code interne et externe grâce aux imports statiques et à une gestion native des packages
    • utilisation d’outils issus d’une vaste communauté de développeurs, comme les linters, bundlers et analyseurs statiques
    • accès aux fonctionnalités JavaScript modernes comme async/await et à un système de types plus flexible
    • réduction des barrières à l’onboarding des nouveaux développeurs et à la participation d’autres équipes

Pourquoi cette transition n’a été possible que récemment

  • Quand Figma a créé sa première base de code mobile, les navigateurs mobiles ne prenaient pas encore en charge WebAssembly, et il était aussi difficile de charger de gros bundles avec de bonnes performances
  • TypeScript en était lui aussi à ses débuts, si bien que Skew, avec son typage statique et son système de types plus strict, représentait alors une option plus réaliste
  • WebAssembly a obtenu un support large sur mobile d’ici 2018, et selon les tests de Figma, les performances mobiles ont atteint un niveau fiable en 2020
  • Les premiers points forts de Skew étaient des optimisations classiques de compilateur comme le constant folding et la suppression des appels virtuels, ainsi que des optimisations spécifiques au web comme la génération de JavaScript utilisant de vraies opérations entières
  • Un benchmark mené en 2020 a montré que le chargement d’un prototype Figma en TypeScript dans Safari pouvait être près de 2 fois plus lent, ce qui bloquait la transition puisque Safari est le seul moteur de navigateur autorisé sur iOS
    • avec iOS 17.4, Apple a ouvert d’autres moteurs de navigateur aux utilisateurs de l’UE, mais WebKit reste le seul moteur disponible pour les utilisateurs des autres régions
  • Par la suite, une grande partie des composants centraux du moteur Skew a été remplacée par leurs équivalents dans le moteur C++, ce qui a réduit le risque de performance lié au passage à TypeScript
    • y compris les chemins de code les plus critiques, comme le chargement de fichiers
    • Figma a ainsi acquis la certitude qu’une éventuelle perte de performance resterait acceptable après migration vers TypeScript
  • Avec la croissance des équipes prototypage et mobile, l’entreprise a aussi pu consacrer des ressources à la migration automatique et à l’amélioration de l’expérience développeur

Une transition de la base de code en 3 phases

  • Lors du premier prototype de migration en 2020, les performances de TypeScript étaient presque 2 fois plus lentes
  • Une fois le support de WebAssembly et le passage du moteur mobile à C++ suffisamment avancés, Figma a profité de la Maker Week pour adapter un prototype existant et démontrer une migration fonctionnelle passant tous les tests
  • L’objectif était de convertir toute la base de code en TypeScript, mais une réécriture manuelle risquait de ralentir le développement, d’introduire des erreurs d’exécution et de dégrader les performances
  • Skew et TypeScript présentaient des différences de sémantique plus profondes qu’un simple passage entre variantes de « JavaScript typé »
    • en TypeScript, les namespaces et classes ne sont initialisés qu’après l’import du fichier
    • un ordre d’import inattendu peut provoquer des erreurs d’exécution
    • Skew rend tous les symboles disponibles à l’exécution à l’échelle de toute la base de code au moment du chargement
  • Figma a développé un transpileur Skew-vers-TypeScript en s’appuyant sur un ancien travail lancé par Evan Wallace
  • Phase 1 : écrire en Skew et construire en Skew

    • le transpileur a été développé sans modifier le processus de build existant
    • le code TypeScript généré était commit dans GitHub pour permettre aux développeurs de voir la forme de la nouvelle base de code
  • Phase 2 : écrire en Skew et construire en TypeScript

    • une fois un bundle TypeScript capable de passer tous les tests unitaires obtenu, Figma a commencé à déployer progressivement en production des builds issus de la base de code TypeScript
    • les développeurs continuaient d’écrire en Skew, et le transpileur convertissait ce code en TypeScript pour mettre à jour le code TypeScript dans GitHub
    • les erreurs de typage du code généré continuaient elles aussi à être corrigées
    • TypeScript pouvait produire un bundle valide même en présence d’erreurs de type
  • Phase 3 : écrire en TypeScript et construire en TypeScript

    • une fois tous les utilisateurs passés par le processus de build TypeScript, Figma a fait du code TypeScript l’unique source de vérité pour le développement
    • l’équipe a attendu un moment sans fusion de code pour arrêter la génération automatique et supprimer le code Skew de la base de code
    • la suppression de l’autogénération et le passage des tâches CI à l’exécution directe des fichiers TypeScript ont été fusionnés un vendredi soir
    • une régression sur la fonctionnalité Smart Animate a été détectée en interne pendant le déploiement progressif, mais le déploiement sous forme de gate a permis de stopper le rollout, corriger le problème, puis revoir le plan

Les problèmes révélés par le transpileur

  • Un compilateur se compose généralement d’un frontend et d’un backend
    • le frontend parse le code d’entrée, effectue les vérifications de type et de syntaxe, puis le convertit en représentation intermédiaire (IR)
    • le backend transforme l’IR en un autre langage
    • le backend du compilateur Skew produisait du JavaScript obfusqué et minifié
  • Un transpileur est un compilateur particulier dont le backend génère du code lisible par les humains, et Figma devait produire du TypeScript lisible à partir de l’IR de Skew
  • La première implémentation, largement inspirée du backend JavaScript de Skew, a été relativement simple, mais de nombreux problèmes difficiles à suivre et à traiter sont apparus ensuite
  • Performances de la déstructuration de tableaux

    • en étudiant l’écart de performances hors ligne entre Skew et TypeScript sur un prototype de test, Figma a constaté un framerate plus faible côté TypeScript
    • la cause venait de la déstructuration de tableaux en JavaScript
    • dans une opération comme const [a, b] = function_that_returns_an_array(), JavaScript n’indexe pas directement le tableau mais construit un itérateur et le parcourt
    • Figma utilisait cette approche pour récupérer des arguments depuis le mot-clé arguments en JavaScript, ce qui ralentissait certains cas de test
    • en générant du code indexant directement le tableau arguments plutôt qu’en utilisant la déstructuration, l’équipe a réduit la latence par frame jusqu’à 25%
  • L’optimisation de suppression des appels virtuels de Skew

    • dans certaines conditions, le compilateur Skew appliquait une optimisation de devirtualization en sortant une fonction de sa classe pour la transformer en fonction globale
    • myObject.myFunc(a, b) pouvait ainsi devenir myFunc(myObject, a, b)
    • TypeScript n’applique pas cette optimisation
    • la régression de Smart Animate se produisait quand myObject était null
    • l’appel devirtualized fonctionnait normalement, alors que l’appel non devirtualized déclenchait une exception d’accès à null
    • Figma a ajouté des logs à toutes les fonctions susceptibles de participer à la devirtualization afin de retrouver les points d’appel concernés
    • après une courte période de collecte, l’équipe a analysé les logs de production et corrigé les appels problématiques
  • Différences d’ordre d’initialisation

    • en Skew, variables, classes, namespaces et fonctions peuvent être déclarés n’importe où dans le code sans se soucier de l’ordre
    • en TypeScript, l’ordre d’initialisation des variables globales ou des définitions de classes est important
    • initialiser une variable statique de classe avant la définition de la classe provoque une erreur à la compilation
    • le transpileur initial n’utilisait pas de namespaces et aplatissait toutes les fonctions dans le scope global pour reproduire un comportement proche de Skew
    • le code obtenu était difficile à lire ; le transpileur a ensuite été modifié pour émettre du code TypeScript dans le bon ordre et réintroduire les namespaces pour améliorer la lisibilité
    • au final, Figma a obtenu un transpileur capable de compiler du TypeScript passant les tests unitaires et offrant des performances équivalentes à celles de Skew
    • quelques petits problèmes ont été corrigés manuellement dans le code source Skew ou après la transition vers TypeScript, plutôt que via de nouvelles modifications du transpileur

Préserver l’expérience de débogage avec les source maps

  • Pendant la transition vers TypeScript, Figma a accordé une grande importance aux source maps afin que les développeurs puissent continuer à déboguer sans interruption
  • Les débogueurs de navigateur ne comprennent que JavaScript, mais les développeurs posent leurs breakpoints dans les sources Skew ou TypeScript
  • Les source maps relient les positions du JavaScript compilé à celles du code source d’origine
    • par exemple, un mapping peut relier helper → c, myInt → a, arrayOfInts → b
  • En général, un unique fichier de source map avec l’extension .map est associé au bundle JavaScript final
  • L’infrastructure existante produisait des source maps Skew → JavaScript, mais en phase 2 le pipeline est devenu Skew → TypeScript → bundling avec esbuild
  • Réutiliser les anciennes source maps telles quelles cassait les correspondances entre JavaScript et code Skew, rendant le débogage impossible
  • Le nouveau processus de build a construit les source maps en 3 étapes
    • Étape 1 : esbuild génère la source map TypeScript → JavaScript ts-to-js.map
    • Étape 2 : le transpileur génère pour chaque fichier Skew une source map Skew → TypeScript
    • Étape 3 : les deux source maps sont composées pour produire la source map finale Skew → JavaScript
  • Grâce à cette source map finale, le nouveau bundle JavaScript pouvait toujours être relié au code Skew, ce qui a permis de préserver l’expérience développeur pendant la phase 2

Gérer la compilation conditionnelle en TypeScript

  • Skew prenait en charge la compilation conditionnelle via des instructions if au niveau supérieur et une option defines fournie au compilateur
  • Cette fonctionnalité permettait de produire différents bundles à partir d’une même base de code
    • le bundle réellement distribué aux utilisateurs
    • un bundle réservé aux tests unitaires
    • des fonctions ou classes utilisant des implémentations différentes selon qu’il s’agissait d’un build debug ou release
  • Comme TypeScript ne dispose pas de compilation conditionnelle, Figma a utilisé après la vérification de type les defines d’esbuild et le dead code elimination pendant l’étape de bundling
  • Avec cette approche, les defines ne peuvent pas influencer la vérification de type
    • du code comme testOnlyFunction, n’existant que lorsque BUILD == "TEST", ne peut pas rester tel quel en TypeScript
  • La solution a consisté à toujours définir les classes et méthodes, puis à faire bifurquer l’implémentation à l’intérieur des méthodes selon la valeur de BUILD
    • si testOnlyFunction est appelée dans un build non destiné aux tests, elle lève une erreur Unexpected call to test-only function
  • Le JavaScript final pouvait ainsi être compilé à l’identique de celui généré par le code Skew d’origine
  • En revanche, certains symboles qui n’existaient auparavant que dans certains modes de compilation se sont retrouvés présents dans tous les modes, ce qui a légèrement augmenté la taille du bundle final
  • Les tests ont montré que cette hausse de taille restait acceptable, et les symboles de niveau supérieur non exportés pouvaient être éliminés par tree-shaking

Après la transition

  • En migrant tout le code Skew vers TypeScript, Figma a modernisé l’une de ses bases de code centrales
  • L’intégration avec le code interne et externe est devenue plus simple, et les développeurs peuvent désormais travailler plus efficacement
  • Au moment où elle a été prise, la décision de démarrer cette base de code en Skew était adaptée aux besoins et aux capacités de Figma
  • Avec la maturité des technologies, TypeScript, qui n’était pas auparavant un choix approprié, est désormais devenu une option pertinente
  • Figma explore maintenant plusieurs pistes pour la suite
    • intégration avec le reste de la base de code
    • gestion des packages beaucoup plus simple
    • utilisation directe des nouvelles capacités du riche écosystème TypeScript
  • Au cours de cette transition, l’entreprise a appris de nombreux aspects de TypeScript, notamment la résolution des imports, le système de modules et la génération de code JavaScript

1 commentaires

 
GN⁺ 2024-05-05
Avis Hacker News
  • Il est déjà surprenant que Figma ait eu un langage personnalisé pour JS, et encore plus surprenant qu’il ait été plus rapide que TS
    Mais il est aussi intéressant qu’ils aient finalement migré vers TS, pourtant plus lent
    On voit ce genre de chose assez souvent : une entreprise crée sa propre technologie au début, puis, en grandissant, finit par migrer vers quelque chose de plus « standard »

    • Ça semble être une trajectoire assez classique. Au départ, une personne brillante comme Evan met en place toute la chaîne d’outils et le cœur du produit, puis finit par partir, être écartée ou perdre de l’intérêt
      Quand l’équipe et le produit grossissent beaucoup, la plateforme est remigrée vers une stack plus familière et plus largement utilisée
      La réussite de ce type de transition dépend énormément de la solidité de la culture d’ingénierie de l’organisation. Je n’ai aucune preuve, mais Evan et les fondateurs semblent avoir construit chez Figma une excellente culture d’ingénierie, avec assez de résilience pour corriger les erreurs quand elles surviennent
    • En lisant de près, on voit que toutes les parties sensibles aux performances ont été déplacées vers du C++/WASM
      À ce stade, il ne restait plus que du code de liaison, et le langage personnalisé n’avait tout simplement plus de raison d’exister
    • Il s’est passé quelque chose de similaire dans la communauté PHP. Facebook est le cas emblématique, mais Yahoo avait aussi pas mal d’optimisations internes, et j’ai vu d’autres entreprises faire leurs propres ajustements pour des raisons de performances ou de sécurité
      Puis arrive un moment où la communauté rattrape son retard et acquiert une dynamique plus forte que celle de l’entreprise, et il devient alors rationnel de revenir à l’implémentation standard
      Je vois le passage de Borg à k8s chez Google comme un peu similaire. Sauf que Google, dans ce cas, a invité la communauté autour du standard qu’il avait lui-même créé
    • Être plus rapide que TS sur un usage étroit, c’est une barre relativement basse. Mais à mesure que l’échelle augmente, il faut aussi considérer le vivier de développeurs disponible sur le marché
      Il faut comparer le coût de développeurs capables d’apprendre un framework totalement nouveau à première vue avec la valeur de développeurs ayant déjà une expérience documentée sur la plateforme ou la technologie utilisée
      Avec du tout sur mesure, on peut tirer des performances énormes de n’importe quel langage ou framework, mais plus un projet doit gérer de cas, plus le nombre de développeurs nécessaires à sa maintenance augmente, et on finit par atteindre un point où un logiciel du commerce devient préférable, même s’il est plus lent et ne correspond pas parfaitement aux besoins
      Sur le long terme, si l’on peut maintenir un niveau de recrutement de type licorne, une stack totalement personnalisée peut peut-être rester viable. Mais la plupart des organisations doivent migrer vers quelque chose que les nouvelles recrues moyennes pourront maintenir à l’avenir, ce qui signifie généralement des produits de fournisseurs logiciels connus et ennuyeux
    • Quelque chose d’inhabituel et d’excentrique comme un langage personnalisé est un désavantage sur un CV non pas pour son implémenteur, mais pour ses simples utilisateurs, par exemple les développeurs qui l’emploient
      Pour les personnes ambitieuses, cela peut être une raison de partir ; cela complique aussi le recrutement et allonge l’onboarding. Et quand on abandonne plus tard le langage personnalisé, il faut en plus lancer un gros projet de transition
      Cela peut parfois en valoir la peine si le gain de performances est énorme, si cela permet d’écrire un code plus sûr, ou si l’objectif est de n’embaucher que des gens qui aiment apprendre de nouveaux langages
  • J’ai travaillé sur ce projet. J’en ai écrit un peu plus sur Twitter : https://twitter.com/andrew_k_chan/status/1786769203912925477
    Le titre de l’article est trompeur. Chez Figma, on utilisait Typescript dans d’autres parties de la base de code depuis presque 10 ans, et pendant presque toute cette période il y avait plus de code Typescript que de code Skew
    Comme l’explique le billet de blog, Skew a été utilisé pour le moteur mobile, puis le lecteur de prototypage, la fonctionnalité de mirroring, et une ou deux zones produit dont je ne me souviens plus

  • Skew n’était pas juste un peu plus rapide que TypeScript
    Selon Evan Wallace, ancien CTO de Figma, c’était 1,5 à 2 fois plus rapide grâce à des optimisations rendues possibles par un système de types plus strict

    • C’est dommage que les navigateurs n’aient pas poursuivi le développement d’un mode "use strong" pour JS
      Il semble y avoir eu de gros obstacles, mais réduire un peu la dynamique du langage pour obtenir des optimisations plus prévisibles me paraît être un bon compromis pour des applications de niveau production
    • L’idée que « c’était 1,5 à 2 fois plus rapide grâce à un système de types plus strict » est probablement moins simple qu’elle n’en a l’air
      Si l’on optimise les chemins d’exécution chauds, l’avantage x2 a de fortes chances de disparaître
      Bien sûr, on peut répondre que cela obligerait à écrire du JS optimisé à de nombreux endroits, avec un impact sur la lisibilité. C’est vrai, mais l’alternative était d’utiliser un langage compilé vers JS entièrement nouveau, avec peu de support outillage et peu de notoriété
      Avec le recul, cela ne semble pas avoir valu le coup, et le billet de blog donne un peu l’impression d’enrober favorablement un ancien choix technique controversé
    • Sur tout l’article, c’est la différence de vitesse x2 qui m’a le plus surpris
      Je me demande s’il serait possible de limiter l’usage de TypeScript au sous-ensemble capable d’atteindre ce niveau de performances
  • Il est intéressant de constater que lorsqu’on fait quelque chose comme const [a, b] = function_that_returns_an_array(), JavaScript ne fait pas un accès direct par index dans le tableau, mais crée un itérateur qui parcourt le tableau
    Pourquoi JS n’indexe-t-il pas simplement directement le tableau lors d’une affectation par déstructuration ?

    • N’importe quel objet peut devenir itérable si on lui ajoute Symbol.iterator, et la déstructuration doit aussi fonctionner avec ce type d’objet. On peut même patcher le Symbol.iterator d’un tableau lui-même, donc la VM doit le prendre en charge
      Array.prototype[Symbol.iterator] = function*() { yield 1; yield 2; yield 3; }
      [...[4, 5, 6]]
      [1, 2, 3]
      Les performances catastrophiques du protocole d’itérateur étaient déjà débattues à l’époque, mais cela a été balayé en disant que l’escape analysis réglerait le problème [0]. Presque 10 ans plus tard, l’escape analysis ne l’a toujours pas résolu, cela sollicite énormément le GC et cela reste médiocre. C’est une mauvaise spécification conçue par des gens qui ne se soucient pas des performances
      Si l’utilisateur n’a pas patché Symbol.iterator, il serait logique que le moteur spécialise la déstructuration et le spreading des tableaux pour éliminer le surcoût du protocole d’itérateur, mais cela pose encore d’autres problèmes pénibles
      [0] https://esdiscuss.org/topic/performance-of-iterator-next-as-...
    • Cela semble aussi venir de l’existence de choses comme les proxies
      Plus étrange encore, sur certains moteurs JavaScript, pour déstructurer un tableau de deux ou trois éléments, la déstructuration d’objet du type {0: foo, 1: bar} peut être plus rapide
  • L’article parle surtout de la conversion effectuée une fois au moment de la migration du codebase, et très peu de l’impact continu sur l’expérience développeur lié à la perte des fonctionnalités pratiques de Skew
    Par exemple, avec TypeScript il est facile de se retrouver dans une situation où il faut importer les fichiers dans le bon ordre, faute de quoi tout peut casser. Et la déstructuration est lente, donc il vaut mieux l’éviter dès qu’un minimum de performance compte
    Après quelques années à utiliser TypeScript, j’ai constaté qu’il y avait des dizaines de pièges de ce genre, certains hérités de JavaScript et d’autres non. Si l’on a beaucoup d’ingénieurs, il faut au minimum un guide de style volumineux
    Je me demande s’il y a eu des ingénieurs tristes de voir disparaître Skew

    • Il était clairement important que les développeurs soient satisfaits du résultat. C’est pourquoi le déploiement comprenait une étape où les développeurs continuaient à écrire en Skew, mais où les modifications étaient automatiquement check-in dans le TS généré
      Cela permettait aux développeurs de voir à quoi ressemblerait le résultat dans les revues de PR et de signaler les problèmes
      Il est vrai qu’il y a quelques pièges en TS du point de vue des performances et de la justesse à l’exécution. Des problèmes comme la déstructuration de tableaux ont été repérés grâce à l’instrumentation et une surveillance stricte
      La disparition de certaines fonctionnalités de Skew, comme la surcharge d’opérateurs et les types entiers, était certes regrettable. Mais au final la migration a été une décision prise par toute l’équipe, et je pense moi aussi que c’était la bonne décision
  • Il est écrit « des fonctionnalités JavaScript modernes comme async/await et un système de types plus flexible » ; cela veut-il dire que Skew n’avait que des callbacks ?

    • Il avait peut-être Promise, non ?
  • Sans bien connaître Figma, je me demande pourquoi ils utilisent WebAssembly

    • Vous savez probablement que Figma est un logiciel de design UX. C’est donc fondamentalement un programme graphique. On dessine des formes, on fait défiler, on zoome
      Et Figma le fait extrêmement bien. Même sur un immense canvas rempli d’écrans d’interface complexes, c’est incroyablement réactif
      Il existe très peu d’applications desktop aujourd’hui qui tournent aussi bien. Je suis convaincu que cette optimisation est une part essentielle du succès de Figma
    • L’édition vectorielle comporte beaucoup de tâches limitées par le CPU. Evan a écrit un billet sur la transition vers WASM : https://medium.com/figma-design/webassembly-cut-figmas-load-...
    • Au départ, l’objectif était d’être un Photoshop dans le navigateur
  • On trouve aussi dans un autre billet de blog des détails intéressants sur la façon dont Figma a créé un DSL TypeScript personnalisé + compilateur pour résoudre des problèmes de sécurité, à savoir les permissions
    https://www.figma.com/blog/how-we-rolled-out-our-own-permiss...

  • C’est un peu frustrant. Chaque grande entreprise a ses propres outils internes, langage, Kubernetes ou autre. Pourquoi ne pas les partager
    Si Skew avait été open source, cela aurait peut-être donné un TypeScript meilleur

    • Skew est open source, mais n’est plus maintenu : https://github.com/evanw/skew
    • Je n’aime pas beaucoup ce point de vue, qui vient généralement d’un manque d’expérience de l’open source
      Le fait d’être open source ne fait pas apparaître des contributions gratuites par magie. Chaque PR un tant soit peu sérieuse implique de longues revues, des discussions, et peut-être même une réécriture
  • J’aime TypeScript, et nous avons même un système full stack en TypeScript, mais ce n’est pas parfait. Configurer TypeScript dans un monorepo est un cauchemar
    Pour que cela reste compréhensible avec les packages internes sous un monorepo pnpm, il faut faire énormément de travail manuel dans tsconfig.json pour que tous les chemins correspondent entre eux
    Et avant l’arrivée de l’excellent package tsx, la chaîne d’outils de production était en pratique quasi impossible à maintenir
    En plus, c’est absurdement lent. À cause de Zod, les performances du serveur de langage TypeScript se dégradaient fortement, si bien qu’on a fini par adopter les références de projet et désactiver la redirection des références de projet
    En résumé, il y a encore beaucoup de marge pour améliorer TypeScript, surtout sur les monorepos et les performances

  • Il faut toutefois garder à l’esprit que Zod est un cas assez exceptionnel en ce qui concerne à quel point il peut ralentir la vérification de types. Par exemple, dans https://dev.to/nicklucas/typescript-runtime-validators-and-d..., un test monte à presque 300 ms, alors que d’autres bibliothèques n’approchent même pas les 100 ms

  • Zod est connu pour être lent. Par exemple, Typebox est bien plus rapide. Je ne dis pas qu’il faut changer, mais que ce n’est pas un problème de TypeScript, ni un problème que TypeScript doit résoudre
    Pour le problème de monorepo, on dirait plutôt que les mêmes réglages ne sont pas utilisés dans tous les packages. Si c’est le cas, je commencerais par corriger cela en imposant une configuration et des standards de code communs. Là encore, ce n’est pas un problème de TypeScript
    Vous utilisiez peut-être ts-node avant tsx ? Si oui, tsx est bien plus robuste. Il fonctionne, tout simplement

  • Ce n’est pas à TypeScript de prendre en charge une combinaison précise d’outils et de bibliothèques ; c’est plutôt aux outils et aux bibliothèques de s’adapter
    J’exploite la plupart d’un monorepo de taille intermédiaire, avec plusieurs applications et de nombreux services, principalement en TypeScript, et cela fonctionne correctement avec une configuration basée sur de simples npm workspaces

  • Dire que TypeScript est lent parce que Zod est lent, c’est un peu comme dire que le C++ est lent parce que JavaScript est lent
    Cela ne veut pas dire que TypeScript est rapide, loin de là, mais comme il est écrit en JavaScript, il lui est aussi difficile d’être rapide
    Cela dit, laisser TypeScript exécuter du code pour faire de l’inférence de types dans une application de grande taille ressemble quand même à un problème qu’on s’est créé soi-même