JSDoc, c’est TypeScript
(culi.bearblog.dev)- En 2023, une PR de refactorisation du dépôt Svelte, convertie vers un code basé sur JSDoc, a attiré l’attention des sceptiques de TypeScript
- L’équipe de Svelte a expliqué qu’il ne s’agissait pas d’une position anti-TypeScript, mais d’une forme de dépendance continue à TypeScript
- L’article insiste sur le fait qu’il ne faut pas opposer JSDoc et TypeScript, car JSDoc fait lui-même partie de TypeScript
- TypeScript agit comme moteur IntelliSense, en prenant en charge à la fois l’interprétation des commentaires JSDoc et l’autocomplétion du code
- Sans étape de build, JSDoc offre les mêmes capacités d’analyse statique et joue en pratique le même rôle que TypeScript dans les projets JS modernes
La PR de Svelte et l’origine de la controverse
- En mai 2023, une PR de refactorisation interne du dépôt Svelte est montée en première page de Hacker News
- Cette PR consistait à déplacer des déclarations de type de fichiers
.tsvers des commentaires JSDoc dans des fichiers.js - Certains y ont vu un rejet des avantages de TypeScript
- Cette PR consistait à déplacer des déclarations de type de fichiers
- Le créateur de Svelte, Rich Harris, a directement expliqué sur HN que « ce n’est pas anti-TypeScript »
- Il a précisé que l’engagement de Svelte envers TypeScript reste très fort
- Après cet épisode, de nombreux articles comparant « TypeScript vs JSDoc » sont apparus, popularisant l’idée de JSDoc comme un « TypeScript sans étape de build »
L’origine et la nature de TypeScript
- À la fin des années 2000 et au début des années 2010, JavaScript était perçu comme un langage manquant d’autocomplétion et de sûreté de typage
- Les développeurs de Microsoft y répondaient en utilisant ScriptSharp pour convertir du code C# en JS
- C’est dans ce contexte que TypeScript est né, au départ essentiellement comme un outil de build destiné à améliorer le développement JS
TypeScript, c’est IntelliSense
- TypeScript n’est pas seulement un langage, il joue aussi le rôle de moteur IntelliSense
- Même sans utiliser de fichiers
.ts, l’autocomplétion, les informations sur les paramètres et la navigation entre symboles sont fournies par le service de langage TypeScript - Dans la plupart des éditeurs, lorsque l’on écrit du code JS, les services TypeScript fonctionnent déjà en arrière-plan
- Même sans utiliser de fichiers
TypeScript, c’est JSDoc
- Le service de langage TypeScript sert aussi à interpréter les commentaires JSDoc
- Le CHANGELOG de TypeScript inclut fréquemment des ajouts liés à JSDoc
- Les projets basés sur JSDoc peuvent aussi être configurés avec
tsconfig.json, et la commandetscpermet d’effectuer la vérification de types
- Autrement dit, les développeurs qui utilisent JSDoc utilisent déjà TypeScript
Retour d’expérience sur des projets basés sur JSDoc
- L’auteur partage son expérience de réécriture du frontend d’un projet existant à partir d’annotations de types JSDoc
- À l’exception de fonctionnalités d’exécution comme les énumérations (
enum), la plupart des expressions TypeScript sont possibles avec JSDoc - Les génériques ont une syntaxe un peu plus complexe, mais poussent à s’appuyer davantage sur l’inférence de types
- À l’exception de fonctionnalités d’exécution comme les énumérations (
- Dans un projet JSDoc, cliquer sur une fonction permet d’aller vers le vrai code, ce qui améliore l’expérience de développement
- L’écosystème d’outils TypeScript reste réutilisable dans les projets JSDoc
- Par exemple, des bibliothèques qui génèrent des types à partir de schémas OpenAPI ou GraphQL peuvent aussi générer des types sous forme de commentaires JSDoc
Conclusion et autres cas
- JSDoc n’est pas une alternative à TypeScript, il partage le même système d’analyse statique
- Il permet d’omettre l’étape de build tout en offrant une sûreté de typage équivalente
- L’article mentionne aussi un cas de migration du projet webpack vers JSDoc
- En tant qu’expert TypeScript, l’auteur affirme clairement : « JSDoc, c’est TypeScript »
1 commentaires
Commentaires sur Hacker News
J’ai résumé ce que j’ai appris en développant et en maintenant, pendant plusieurs années, des logiciels web et de robotique en Python/JavaScript
Les types existent même si on ne les explicite pas, et si on ne les explicite pas, ils finissent par n’exister que dans notre tête
Mais la mémoire humaine est très volatile et difficilement accessible aux autres
Donc le typage est un excellent moyen de documentation
JSDoc et TypeScript sont des formats standard pour exprimer les types, et chacun a ses avantages et ses inconvénients
L’important est de définir les types de manière cohérente et prévisible
Un vérificateur de types, c’est la manière qu’a l’ordinateur de dire : « alors prouve-le »
Tous les programmes n’ont pas besoin du même niveau de preuve, et exiger trop de preuves peut être du gaspillage
C’est pourquoi je préfère les langages qu’on peut « prouver » seulement autant que nécessaire
En travaillant, j’ai appris de façon très concrète que « les autres » incluent aussi mon moi du futur
Rust permet d’assouplir les contraintes avec unsafe, Arc, clone, mais en échange il oblige à choisir explicitement quelles contraintes ne sont pas prouvées
À l’inverse, dans les langages où il n’est pas nécessaire de « prouver », il est difficile de savoir quelle approche est prise en interne
L’approche de Rust peut sembler souple au départ comme Python, mais elle est ensuite bien plus avantageuse en lisibilité et extensibilité
Mon intention n’était pas de défendre un outil en particulier, mais simplement de souligner que tous deux sont des moyens d’exprimer un système de types
Les langages à typage statique étaient bien plus faciles à gérer dans les projets d’équipe, et encore aujourd’hui je préfère les types statiques quand c’est possible
Quand on regarde les définitions de types TypeScript ajoutées après coup à des bibliothèques JS existantes, la complexité est énorme
Un seul type erroné peut faire échouer toute la compilation
Au final, les langages dynamiques doivent être utilisés en “prenant soi-même la responsabilité”
J’aime tout ce qu’on peut faire en JavaScript sans étape de build
La combinaison HTML/CSS moderne, Web Components et JSDoc est sous-estimée
Ce n’est pas adapté à tout le monde, mais je pense que c’est un candidat tout à fait moderne pour une stack frontend
Et grâce à des fonctionnalités comme le HMR, le coût de l’étape de build a aussi beaucoup diminué
Je passe toujours par Vite ou Webpack, donc je ne ressens pas vraiment les avantages du JS sans build
J’aimerais qu’il existe un moyen plus simple de construire des composants complexes
Suivi des requêtes réseau, saut direct au code source, points d’arrêt : le débogage devient bien plus intuitif
À mesure que la taille du projet augmente, cet environnement devient d’autant plus utile
À l’époque où les SPA étaient à la mode, JSDoc était le sauveur de la gestion des types
Puis Google Closure Compiler est arrivé en apportant une sécurité de types basée sur JSDoc, et TypeScript a pris en charge le (TS)JSDoc avec sa propre syntaxe
La communauté a finalement choisi TypeScript et Closure Compiler a disparu
Ainsi, le (TS)JSDoc est resté comme un vestige de l’époque où MS rivalisait avec Google
Aujourd’hui, TS offre bien plus de fonctionnalités, comme les génériques, les enum, les utility types, les tests de types Vitest, les type guards, etc.
J’utilise TS et JSDoc ensemble — TS pour le code, JSDoc pour la documentation (@link, @see, @deprecated, @example, etc.)
Génériques, utility types, type guards, parsing d’expressions régulières : la plupart des fonctionnalités de TS sont aussi utilisables avec JSDoc
Dans un projet personnel, j’ai tout implémenté en JSDoc, y compris les génériques
Dire que le (TS)JSDoc est un vestige du passé est une information erronée, qu’il ne faudrait pas relayer sans vérification
On dit qu’il y a beaucoup de types qu’on ne peut pas exprimer avec JSDoc, mais j’aurais aimé qu’il adopte une approche à l’échelle de tout le langage comme Flow
TypeScript aurait aussi pu faire cela, et je ne comprends pas pourquoi il ne l’a pas fait
Je pensais comme ça auparavant moi aussi, mais j’ai changé d’avis en refactorisant un projet vers JSDoc
Avec
@template, on peut définir des emplacements génériques en JSDocExemple :
Lien connexe
Un paquet écrit en JSDoc offre une bonne expérience développeur, car un clic CMD/CTRL permet d’aller au vrai code
Lors d’un meetup il y a 5 ans, un intervenant avait dit que « si vous n’aimez pas TypeScript, JSDoc est une alternative »
J’avais expliqué que dans les deux cas, c’est finalement du TypeScript, mais mon supérieur ne m’avait pas cru
JSDoc et TS expriment tous deux explicitement les types, mais la syntaxe TS est bien plus puissante
Malgré cela, JSDoc reste un bon choix pour ceux qui veulent conserver un environnement JS tout en profitant des outils de typage
En contre-argument, JSDoc n’est pas TypeScript
Les types définis avec
@typedefsont automatiquement exportés, et il n’existe aucun moyen de contrôler celaIssue connexe
À cause de cela, lors du développement de bibliothèques, IntelliSense exposait les éléments de façon désordonnée, ce qui était gênant
On peut copier tel quel un fichier “my-component.js” et il fonctionne sans build
Mais pour les grands projets, je préfère la syntaxe TS
@import, on peut résoudre la plupart des casJe suis d’accord avec l’affirmation selon laquelle « JSDoc n’est pas une alternative à TypeScript »
JSDoc fournit lui aussi une analyse statique, mais sans étape de build
Voir la documentation officielle de Node
Mais le TS basé sur JSDoc fonctionne aussi dans le navigateur
Personnellement, je préfère la lisibilité de la syntaxe TS, et avec des outils comme
swc, la suppression des types est déjà suffisamment rapideSi TypeScript a fini par l’emporter sur les autres alternatives, c’est parce qu’il est resté un vérificateur de types plutôt qu’un nouveau langage
Au début, son orientation a quelque peu hésité, mais elle a été corrigée au bon moment, et aujourd’hui, même les enums sont rarement utilisés dans la plupart des bases de code
Dans VSCode, si on active le réglage « TypeScript: Prefer Go To Source Definition », on peut accéder au vrai code source
En ajoutant aussi
declarationMap: truedanstsconfig, cela fonctionne de manière plus précisePersonnellement, je préfère presque toujours voir le code source avec cmd+click