Introduction : Pourquoi « ça compile » est un mauvais critère
\nImaginez la situation : vous ouvrez une Pull Request sur GitHub, vous voyez le coche verte du CI et vous entendez une voix intérieure : « Les types correspondent — donc le code est correct ». Cela vous semble familier ? Si oui, vous tombez dans le piège que nous appelons « le faux sentiment de sécurité de TypeScript ».
\nTypeScript n'est pas une panacée. Il ne détecte pas les erreurs logiques, ne vérifie pas les exigences métier et ne garantit certainement pas que votre code ne plantera pas à l'exécution. C'est pourquoi la code review en TypeScript ne consiste pas à « jeter un coup d'œil », mais à adopter une approche systématique. Dans cet article, je vais vous dire sur quoi il faut vraiment se concentrer lorsque vous révisez du code TypeScript. Je tiens un blog sur PythonLib, et ici nous avons l'habitude d'aller en profondeur — préparez-vous.
\n\n1. Le type any : un chiffon rouge
\nLe plus évident, mais curieusement le plus fréquent. any est l'interrupteur d'arrêt de TypeScript. Si vous voyez any dans le code, votre tâche est de comprendre : est-ce de la paresse de l'auteur ou un cas vraiment justifié ?
Mauvais exemple :
\nfunction processData(data: any) {\n return data.name.toLowerCase();\n}\nIci, nous perdons toute information sur le type. Si data arrive null ou undefined — bonjour l'erreur à l'exécution.
Bon exemple :
\ninterface UserData {\n name: string;\n age?: number;\n}\n\nfunction processData(data: UserData) {\n return data.name.toLowerCase();\n}\nQue vérifier lors de la code review : Si any est tout de même utilisé (par exemple, pour travailler avec du JSON de structure inconnue), l'auteur exige-t-il une validation à l'entrée ? Souvent, any masque l'absence d'un typage correct pour les données externes.
2. Strict mode : ne le désactivez pas
\nLa première chose que je vérifie dans tsconfig.json est le flag strict: true. S'il n'est pas présent, vous vous privez de toute une série de vérifications : strictNullChecks, noImplicitAny, strictFunctionTypes et autres.
Sans strictNullChecks, vous pouvez écrire :
const user = getUser(); // peut retourner null\nconst name = user.name; // TS ne râlera pas, mais à l'exécution ça plantera\nLors de la code review : Si vous voyez que le projet fonctionne sans strict mode — tirez la sonnette d'alarme. C'est une dette technique qui s'accumule de manière exponentielle. Il vaut mieux passer une journée à activer le strict mode et corriger les erreurs, qu'un mois à traquer les bugs en production.
\n\n3. Les génériques : puissance et responsabilité
\nLes génériques sont un super-pouvoir de TypeScript. Mais un grand pouvoir implique de grandes responsabilités. Lors de la code review, je regarde toujours : l'auteur n'a-t-il pas trop complexifié les types ?
\nExemple de complexité excessive :
\nfunction identity<T extends Record<string, unknown>>(arg: T): T {\n return arg;\n}\nPourquoi limiter T à Record<string, unknown> si nous retournons simplement la même chose ? Il suffit de :
function identity<T>(arg: T): T {\n return arg;\n}\nQue vérifier :
\n- \n
- Les génériques sont-ils utilisés là où la flexibilité est nécessaire, ou pourrait-on se contenter d'un type concret ? \n
- N'y a-t-il pas de contraintes (extends) redondantes qui nuisent à la réutilisation ? \n
- Les types sont-ils correctement inférés — l'utilisateur n'est-il pas obligé de spécifier manuellement
<SomeType>là où TS aurait pu le deviner tout seul ? \n
4. unknown vs any : choisissez la bonne arme
\nLorsque vous travaillez avec des données dont le type vous est inconnu (API, localStorage, saisie utilisateur), utilisez unknown plutôt que any. unknown vous oblige à vérifier explicitement le type avant de l'utiliser.
Mauvais :
\n<