Mathieu Eveillard

JavaScript : quand le compilateur, c’est vous

JavaScript : quand le compilateur, c’est vous

On trouve encore des développeurs JavaScript pour soutenir l’idée qu’un vrai bon développeur n’aurait pas besoin de TypeScript. Voilà qui est intéressant.

Le doute tient chez moi une place importante, j’en fais même une vertu cardinale. Mais là, permettez-moi de dire que c’est tout simplement absurde.

Examinons ça de plus près 🔎

« Le typage c’est contraignant, alors je fais sans »

Un classique, qui a le mérite d’être honnête mais qui me laisse inquiet sur la qualité du code produit.

En effet, si j’écris (en TypeScript) :

type WrappedNumber = {
  value: number;
};

const array: WrappedNumber[] = [
  { value: 0 }, //
  { value: 1 },
  { value: 3 },
];

const result = array.find(({ value }) => value === 2);

console.log(result.value);

Le compilateur va tout de suite indiquer ts(2532): Object is possibly 'undefined'. À raison, puisque la méthode Array.find() renvoie undefined si aucun élément du tableau ne satisfait le prédicat.

Le compilateur n’est pas là pour nous embêter mais plutôt pour révéler un problème qui existe, que l’on utilise ou non un système de types. Dire « non » au compilateur, c’est un peu comme dire « La gravitation ? J’aime pas trop ça, je vais faire sans ».

Dit autrement, se passer de tout système de types ne fait pas disparaître le problème. C’est seulement qu’il apparaîtra en production plutôt qu’en développement. En effet, c’est bien mieux 👌

Quelqu’un me fait remarquer qu’on pourrait effectuer ces vérifications à l’exécution et truffer notre code de if. En effet : cela reviendrait peu ou prou à écrire à la main un compilateur sous-optimisé. Y’a du Nobel dans l’air.

« Pas besoin de typage, il me suffit de regarder l’implémentation »

Autrement dit : « J’ai pas besoin de compilateur puisque je sais que .find() peut renvoyer undefined ! » De mieux en mieux, vous proposez donc de faire la compilation de tête. Changez rien, les gars, z’êtes au top 👌

Examinons le code suivant (JavaScript, cette fois-ci) :

const random = (min, max, generator) => min + (max - min) * generator();

random(1, 10, "generator");

À l’exécution, ce code produit l’erreur suivante : Uncaught TypeError: generator is not a function.

Pour éviter cette erreur, j’aurais dû lire l’implémentation de la fonction, seule façon de savoir que ledit générateur doit être une fonction qui renvoie un nombre. C’est ça, faire la compilation de tête.

Donc oui, le typage ça peut être dur. Mais « si ça fait mal, c’est que ça fait du bien », disait Jacques Rouxel, père des Shadoks. En effet, je mets au défi quiconque de construire une application d’ampleur en JavaScript pur. J’entends par là une application avec de vrais enjeux métier, des centaines de milliers de lignes de code et une équipe de développement constituée de plus de 1 développeur.

« Je fais des tests, donc je n’ai pas besoin de système de types »

Finissons sur une note plus subtile et ouvrons les chakras. Cette phrase, je ne l’ai bien sûr jamais entendue, mais elle constituerait un argument intéressant.

Sauf que les tests sont bien moins efficaces que le typage. Cette citation de Scott Wlaschin, grand nom du Domain-Driven Design et de la programmation fonctionnelle, nous en donne assez bien l’intuition :

Unit tests have been compared with shining a flashlight into a dark room in search of a monster. Shine the light into the room and then into all the scary corners. It doesn’t mean the room is monster free — just that the monster isn’t standing where you’ve shined your flashlight.

Si vous voulez aller plus loin sur le sujet, je ne peux que vous recommander cette excellente conférence de Julien Truffaut. Quoi qu’il en soit, typage et tests sont bien évidemment complémentaires.

Allez, je vous laisse, j’ai d’autres choses à faire que compiler du code de tête 😉

← Tous les articles