Comment Typescript m'a-t-il déçu et cela en vaut-il la peine?



Avant de commencer, je tiens à mentionner que je suis un fan de TypeScript. C'est mon langage de programmation principal pour les projets front-end sur React et pour tout travail backend que je fais dans Node. Je suis complètement pour Typescript, mais il y a des moments qui me dérangent et dont je voulais raconter cet article.

J'ai écrit exclusivement sur TypeScript au cours des trois dernières années pour de nombreuses entreprises différentes, donc à mon avis, TypeScript fait au moins quelque chose de bien ou ferme certains besoins.

Malgré son imperfection, TypeScript est entré dans le développement frontal principal et se classe septième dans la liste des langages de programmation les plus populaires selon le rapport sur les compétences des développeurs HackerRank .

Toute équipe de développement, qu'elle soit grande ou petite, écrit en TypeScript ou non, en vaut toujours la peine pour la sécurité:

  • Assurez-vous que les tests unitaires bien écrits couvrent autant de code que possible en production.
  • Utilisez la programmation par paires: une paire d'yeux supplémentaire aidera à détecter des choses plus graves que de simples erreurs de syntaxe
  • Construisez qualitativement un processus de révision de code et identifiez les erreurs que la machine ne peut pas trouver
  • Utilisez linter - comme eslint

Bien que TypeScript ajoute un niveau de sécurité supplémentaire en plus de tout cela, mais à mon avis, il est très loin derrière les autres langages à cet égard. Je vais vous expliquer pourquoi.

TypeScript n'est pas un système de type fiable


Je pense que cela peut être le principal problème avec TypeScript, mais permettez-moi d'abord de déterminer quels sont les systèmes de type fiables et non fiables .

Système de type robuste


Un système de type fiable garantit que votre programme ne se retrouve pas dans des états non valides. Par exemple, si le type statique d'une expression est une chaîne , lorsqu'elle est évaluée au moment de l'exécution, vous êtes assuré d'obtenir uniquement une chaîne .

Dans un système de type fiable, vous ne serez jamais dans une situation où l'expression ne correspond pas au type attendu, ni au moment de la compilation ni au moment de l'exécution.

Bien sûr, il existe différents degrés de fiabilité, ainsi que diverses interprétations de la fiabilité. TypeScript est quelque peu fiable et détecte les erreurs de type:

// Type 'string' is not assignable to type 'number' const increment = (i: number): number => { return i + "1"; } // Argument of type '"98765432"' is not assignable to parameter of type 'number'. const countdown: number = increment("98765432"); 

Système de type non sécurisé


Tapuscrit déclare ouvertement que la fiabilité à 100% n'est pas son objectif. Même le numéro «non cible» 3 sur la liste «non cible» de TypeScript indique clairement:
Avoir un système de type fiable ou «prouvablement correct» n'est pas notre objectif. Au lieu de cela, nous nous efforçons de trouver un équilibre entre précision et performances.

Cela signifie qu'il n'y a aucune garantie que la variable est d'un type spécifique au moment de l'exécution. Je peux illustrer cela avec l'exemple un peu artificiel suivant:

 interface A { x: number; } let a: A = {x: 3} let b: {x: number | string} = a; bx = "unsound"; let x: number = ax; // unsound axtoFixed(0); // WTF is it? 

Le code ci-dessus ne fonctionne pas, car il est connu que ax est un nombre de l'interface A. Malheureusement, après quelques feintes avec réaffectation, il se transforme en chaîne et ce code se compile, mais avec des erreurs au moment de l'exécution.

Malheureusement, cette expression se compile sans erreur:

 axtoFixed(0); 

Cette fiabilité n'est pas l'objectif du langage est probablement l'un des plus gros problèmes de TypeScript. Je reçois toujours beaucoup d'erreurs d'erreur d'exécution lors de l'exécution que le compilateur tsc ne détecte pas, mais que le compilateur aurait remarqué si un système de type fiable existait dans TypeScript. TypeScript est maintenant un pied dans le camp des langages "fiables", et l'autre dans le "peu fiable". Cette approche de demi-mesure est basée sur n'importe quel type, dont je parlerai plus tard.

Je suis frustré par le fait que le nombre de tests que j'écris n'a pas diminué du tout avec la transition vers TypeScript. Quand je viens de commencer, j'ai décidé par erreur que je pouvais réduire la routine fastidieuse d'écrire un grand nombre de tests unitaires.

TypeScript conteste l'état actuel des choses en faisant valoir que la réduction des coûts cognitifs lors de l'utilisation de types est plus importante que la fiabilité.

Je comprends pourquoi TypesScript a choisi un tel chemin et il y a une opinion que TypeScript ne serait pas si populaire si la fiabilité du système de type était garantie à 100%. Cette opinion n'a pas résisté au test - le langage Dart gagne rapidement en popularité, ainsi que l'utilisation généralisée de Flutter. Et on fait valoir que la fiabilité des types est l'objectif de Dart.

L'insécurité et les différentes façons dont TypeScript fournit une «sortie d'urgence» de la frappe forte le rendent moins efficace et, malheureusement, le rendent «mieux que rien» pour le moment. Je serais heureux si à mesure que TypeScript gagnait en popularité, davantage d'options de compilateur devenaient disponibles, permettant aux utilisateurs expérimentés de rechercher une fiabilité à 100%.

TypeScript ne garantit aucune vérification de type lors de l'exécution


La vérification de type à l'exécution n'est pas l'objectif de TypeScript, donc mon souhait ne se réalisera probablement jamais. La vérification du type au moment de l'exécution est utile, par exemple, lorsque vous travaillez avec des données JSON renvoyées par des appels d'API. Il serait possible de se débarrasser de toute une catégorie d'erreurs et de nombreux tests unitaires, si nous pouvions contrôler ces processus au niveau du système de type.

Comme nous ne pouvons rien garantir lors de l'exécution, cela peut facilement se produire:

 const getFullName = async (): string => { const person: AxiosResponse = await api(); //response.name.fullName may result in undefined at runtime return response.name.fullName } 

Il existe quelques bibliothèques d'assistance comme io-ts , ce qui est génial, mais cela peut signifier que vous devez dupliquer vos modèles.

Type effrayant toute option stricte


Le type any signifie "any" et le compilateur autorise toute opération ou affectation d'une variable de ce type.

TypeScript fonctionne bien pour les petites choses, mais les gens ont tendance à mettre le type any sur tout ce qui prend plus d'une minute. J'ai récemment travaillé sur un projet Angular et j'ai vu beaucoup de code comme celui-ci:

 export class Person { public _id: any; public name: any; public icon: any; 

TypeScript vous permet d'oublier le système de type.

Vous pouvez casser le type de n'importe quoi avec n'importe quel :

 ("oh my goodness" as any).ToFixed(1); // remember what I said about soundness? 

L'option stricte inclut les options de compilation suivantes, qui rendent tout plus fiable:

  • --strictNullChecks
  • --noImplicitAny
  • --noImplicitThis
  • --toujoursStrict

Il existe également une règle eslint @ typescript-eslint / no-explicit-any .

La distribution de tout peut ruiner la fiabilité de votre code.

Conclusion


Je dois répéter que je suis un fan de TypeScript et que je l'utilise dans mon travail quotidien, mais je pense qu'il est imparfait et que le battage médiatique qui l'entoure n'est pas entièrement justifié. Airbnb affirme que TypeScript a permis d'éviter 38% des erreurs . Je suis très sceptique quant au pourcentage si précisément indiqué. TypeScript n'améliore pas ou ne combine pas toutes les pratiques existantes de bon code. Je dois encore écrire une tonne de tests. Vous pourriez dire que j'écris plus de code, donc je dois écrire autant de tests. Je reçois toujours beaucoup d'erreurs d'exécution inattendues.

TypeScript n'offre que la vérification de type de base, et le fait que la fiabilité et la vérification de type à l'exécution ne sont pas leur objectif laisse TypeScript dans le monde des demi-mesures, à mi-chemin entre le meilleur monde et celui dans lequel nous codons maintenant.

TypeScript est génial grâce au bon support des IDE tels que vscode, où nous obtenons un retour visuel pendant le processus d'impression.


Erreur TypeScript dans vscode

TypeScript améliore également le refactoring et les changements de rupture de code (tels que les changements dans les signatures de méthode) qui sont instantanément identifiés au démarrage du compilateur TypeScript.
TypeScript fournit une bonne vérification de type et c'est certainement mieux que pas de vérification de type ou un simple eslint, mais je pense que TypeScript peut être beaucoup mieux et les options de compilation nécessaires pourraient plaire à ceux qui veulent plus du langage.



Abonnez-vous à notre développeur Instagram


Source: https://habr.com/ru/post/fr485206/


All Articles