Rendez votre code JavaScript robuste avec le flux

JavaScript a toujours été un langage de programmation important, étant le seul langage qui fonctionne de manière fiable dans le navigateur. Les tendances récentes en matière de développement frontal ainsi que de développement back-end basé sur Node.js ont poussé l'ampleur et la complexité des applications JavaScript. 

Les grandes applications développées par de grandes équipes peuvent tirer parti de la vérification de type statique, qui manque à JavaScript dans vanilla. Flow a été développé par Facebook pour résoudre ce problème. C'est un vérificateur de type statique qui s'intègre dans votre processus de développement, détecte de nombreux problèmes à un stade précoce et vous aide à progresser rapidement..

Qu'est-ce que Flow??

Flow est un outil qui vérifie votre code JavaScript annoté et détecte divers problèmes qui, sans lui, seraient découverts uniquement au moment de l'exécution (ou pire, ne pas découvert et corrompu vos données). Voici un exemple rapide.

// fonction @flow getGreeting (name: string): string return 'Hi, $ name';  const http = require ("http"); const greeting = getGreeting ("Gigi") const port = 8888 console.log ('Écoute sur le port $ port…') http.createServer (fonction (demande, réponse) response.writeHead (200, "Content-Type ":" text / plain "); response.write (message d'accueil); response.end ();). listen (port);

Flux vs TypeScript

Avant de plonger dans les détails essentiels de Flow, il est intéressant de le comparer à d'autres alternatives, et en particulier à TypeScript. TypeScript est un sur-ensemble strict de JavaScript développé par Microsoft. Tout programme JavaScript est également un programme TypeScript.. 

TypeScript ajoute des annotations de type facultatives et, globalement, poursuit le même objectif que Flow. Cependant, il existe des différences importantes. TypeScript est un langage de programmation distinct qui compile en JavaScript, tandis que les annotations Flow doivent être supprimées pour revenir à un code JavaScript valide.. 

TypeScript a un excellent outil et un support IDE. Flow rattrape son retard (par exemple, JetBrains WebStorm a une intégration native de Flow).

La différence philosophique la plus importante est que Flow met l'accent sur la solidité. TypeScript 1.0 n'a pas capturé les erreurs null; TypeScript 2.0 avec des contrôles nuls stricts mesurés jusqu'à Flow à cet égard. Mais dans d’autres aspects, tels que les conteneurs génériques ou le typage, TypeScript est plus permissif et laisse passer diverses catégories d’erreurs (seul le typage structurel est vérifié)., ne pas typage nominal).

TypeScript, en tant que son propre langage, ajoute des concepts et des fonctionnalités de langage telles que des classes, des interfaces, des indicateurs de visibilité (public, privé, en lecture seule) et des décorateurs. Ces fonctionnalités facilitent la compréhension et l'utilisation par les personnes issues des langages orientés objet classiques tels que C ++, Java et C #..

Installation

Les annotations Flow n'étant pas du code JavaScript standard, elles doivent être supprimées avant le déploiement de votre application. Voici comment installer flow et flow-remove-types via yarn: fil ajouter --dev flux-bin flux-supprimer-types

Vous pouvez ajouter quelques scripts à votre fichier package.json pour automatiser le processus:

 "scripts": "build": "flow-remove-types src / -d lib /", "prepublish": "yarn run build" 

Vous devez exécuter le script prepublish avant de publier votre code dans le registre npm..

Pour d’autres options d’installation (par exemple, avec npm ou babel), consultez le guide d’installation de Flow..

Pour terminer l'installation, tapez: fil courir flux init

Cela créera le fichier .flowconfig requis..

Type de système

Flow a deux objectifs importants: précision et rapidité. Son système de types a été conçu pour atteindre ces objectifs..

Précision

La précision est obtenue en analysant la manière dont le code interagit avec les types, annotés ou déduits. Toute incompatibilité soulève une erreur de type. Les types annotés prennent en charge le typage nominal, ce qui signifie que deux types différents possédant les mêmes attributs sont distingués l'un de l'autre et ne peuvent pas être substitués. Le type d'une variable est défini comme l'ensemble des valeurs d'exécution que la variable peut recevoir.. 

La vitesse

Le flux est rapide en raison de la combinaison de la modularité et du traitement distribué. Les fichiers sont analysés en parallèle et les résultats sont fusionnés ultérieurement via une mémoire partagée efficace pour effectuer une vérification de type de programme complet..

Types pris en charge

Flow prend en charge de nombreux types. Outre les types primitifs, il prend également en charge les éléments suivants:

  • Objet
  • Tableau
  • Tout
  • Peut être
  • Variable
  • Tuple
  • Classe
  • Interface
  • Générique

Annotations de type

Flow vous permet de déclarer des types et de limiter les variables et les paramètres aux valeurs sélectionnées:

tapez Two2Four = 2 | 3 | 4 fonction doubleIt (numéro: Deux-Quatre) numéro de retour * 2 console.log (doubleIt (3)) Sortie: 6 

Si vous dépassez la plage valide, vous obtiendrez une erreur:

console.log (doubleIt (3)) Sortie: erreur: src / main.js: 30 30: console.log (doubleIt (5)) // erreur ^ nombre. Ce type est incompatible avec le type attendu de 24: fonction doubleIt (numéro: Two2Four) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 

Vous pouvez également définir des types complexes, y compris des sous-types. Dans l'exemple de code suivant, le type Warrior est un sous-type de Person. Cela signifie que vous pouvez renvoyer un guerrier en tant que personne du bats toi() une fonction. Cependant, renvoyer null est interdit.

type Person = nom: chaîne, âge: nombre type Warrior = nom: chaîne, âge: nombre, force: nombre let redWolf: Warrior = nom: "Red Wolf", age: 24 ans, force: 10 let skullCrusher: Warrior = name: "Crull Crusher", âge: 27 ans, force: 11 combat de fonction (w1: Guerrier, w2: guerrier): Personne if (w1.strength> w2.strength) return w1 if ( w2.strength> w1.strength) return w2 return null Sortie: trouvé 1 erreur $ flow Erreur: src / main.js: 47 47: return null ^^^^ null. Ce type est incompatible avec le type de retour attendu de 39: function fight (w1: Warrior, w2: Warrior): Person ^^^^^^ type d'objet, erreur 1 trouvée 

Pour y remédier, retournons le jeune guerrier si les deux guerriers ont la même force:

combat de fonction (w1: guerrier, w2: guerrier): personne if (w1.strength> w2.strength) retour w1 if (w2.strength> w1.strength) retour w2 return (w1.age < w2.age ? w1 : w2)  let winner = fight(redWolf, skullCrusher) console.log(winner.name) Output: Skull Crusher 

Flow permet un contrôle encore plus précis via l'extension de classe, l'invariance, la co-variance et la contre-variance. Consultez la documentation Flow sur la variance.

Configuration

Flow utilise le fichier de configuration .flowconfig situé dans le répertoire racine de vos projets. Ce fichier contient plusieurs sections vous permettant de configurer les fichiers que Flow doit vérifier et les nombreux aspects de son fonctionnement.. 

Comprendre

le [comprendre] section contrôle quels répertoires et fichiers doivent être vérifiés. Le répertoire racine est toujours inclus par défaut. Les chemins dans le [comprendre] les sections sont relatives. Une seule étoile est un caractère générique pour tout nom de fichier, extension ou nom de répertoire. Deux étoiles sont un joker pour n’importe quelle profondeur de répertoire. Voici un échantillon [comprendre] section:

[include]… /externalFile.js… / externalDir /… /otherProject/*.js… / otherProject / ** / coolStuff /

Ignorer

le [ignorer] section est le complément de [comprendre]. Les fichiers et répertoires que vous spécifiez ici ne seront pas vérifiés par le flux. Étrangement, il utilise une syntaxe différente (expressions régulières OCaml) et nécessite des chemins absolus. Changer cela est sur la feuille de route de l'équipe Flow.

En attendant, rappelez-vous que la section include est traitée en premier, suivie de la section ignore. Si vous incluez et ignorez le même répertoire et / ou le même fichier, celui-ci sera ignoré. Pour résoudre le problème du chemin absolu, il est courant de préfixer chaque ligne avec .*. Si vous voulez ignorer les répertoires ou les fichiers sous la racine, vous pouvez utiliser le  espace réservé au lieu de .*. Voici un échantillon [ignorer] section:

[ignore]. * / __ teste __ /. *. * / src / \ (foo \ | bar \) / .*. * \. ignore \ .js /ignore_me.js

Libs

Toute application JavaScript non triviale utilise de nombreuses bibliothèques tierces. Flow peut vérifier comment votre application utilise ces bibliothèques si vous fournissez des fichiers spéciaux libdef contenant des informations de type sur ces bibliothèques.. 

Flow recherche automatiquement les fichiers libdef dans le sous-répertoire "typé" de votre projet, mais vous pouvez également indiquer le chemin des fichiers libdef dans la section [libs]. Ceci est utile si vous maintenez un référentiel central des fichiers libdef utilisés par plusieurs projets..

Importer des définitions de types existantes et créer les vôtres si la bibliothèque cible ne fournit pas ses propres définitions de types est assez simple. Voir:

  • Flow Documentation: Définitions de la bibliothèque
  • Flow Documentation: Création de définitions de bibliothèque
  • GitHub: Importer et utiliser les définitions de la bibliothèque

Des peluches

Flow a plusieurs règles de peluche que vous pouvez contrôler et déterminer comment les traiter. Vous pouvez configurer les règles à partir de la ligne de commande, dans les commentaires de code ou dans [lints] section de votre fichier de configuration. Je parlerai de la charpie dans la section suivante, mais voici comment le configurer en utilisant le [lints] section:

[lints] all = warn untyped-type-import = erreur sketchy-null-bool = off

Les options

le [options] la section est l'endroit où vous devez dire à Flow comment se comporter dans une variété de cas qui ne méritent pas leur propre section, ils sont donc tous regroupés.

Il y a trop d'options pour toutes les énumérer ici. Certains des plus intéressants sont:

  • tout: défini sur true pour vérifier tous les fichiers, pas seulement ceux avec @flow
  • Emoji: défini sur true pour ajouter des émoticônes aux messages d'état
  • module.use_strict: mis à true si vous utilisez un transpiler qui ajoute "use strict;"
  • suppress_comment: une expression rationnelle qui définit un commentaire pour supprimer les erreurs de flux sur la ligne suivante (utile pour le code en cours)

Découvrez toutes les options du guide de flux pour la configuration des options..

Version

Flow et son format de fichier de configuration évoluent. le [version] Cette section vous permet de spécifier la version de Flow pour laquelle le fichier de configuration est conçu pour éviter des erreurs de confusion..

Si la version de Flow ne correspond pas à la version configurée, Flow affiche un message d'erreur..

Voici quelques façons de spécifier les versions prises en charge:

[version] 0.22.0 [version]> = 0.13.0 <0.14.0 [version] ^1.2.3 

La version caret conserve le premier composant non nul de la version corrigé. Alors ^ 1.2.3 se développe à la gamme> = 1.2.3 < 2.0.0, and ^ 0.4.5 se développe dans la plage> = 0.4.5 < 0.5.0.

Utiliser Flow à partir de la ligne de commande

Flow est un programme client-serveur. Un serveur de flux doit être en cours d'exécution et le client s'y connecte (ou le démarre s'il n'est pas en cours d'exécution). La CLI de Flow comporte de nombreuses commandes et options utiles à des fins de maintenance et d’introspection, ainsi que pour remplacer temporairement la configuration à partir de .flowconfig..

Dactylographie flux --help montre toutes les commandes et options. Pour obtenir de l'aide sur une commande spécifique, tapez couler --Aidez-moi. Par exemple:

$ flow ast --help Utilisation: flow ast [OPTION]… [FILE] par ex. flux ast foo.js ou flux ast < foo.js --from Specify client (for use by editor plugins) --help This list of options --pretty Pretty-print JSON output --tokens Include a list of syntax tokens in the output --type Type of input file (js or json) 

Les commandes importantes sont:

  • init: générer un fichier .flowconfig vide
  • vérifier: faire une vérification complète du flux et imprimer les résultats 
  • ls: afficher les fichiers visibles dans Flow
  • statut (valeur par défaut): affiche les erreurs de flux actuelles provenant du serveur de flux.
  • suggérer: suggérer des types pour le fichier cible

Linting With Flow

Flow dispose d'un framework de linting qui peut être configuré via le fichier .flowconfig comme vous l'avez vu précédemment, via des arguments de ligne de commande ou dans des fichiers de code utilisant des commentaires flowlint. Toutes les méthodes de configuration consistent en une liste de paires clé-valeur où la clé est une règle et la valeur est la gravité.. 

Règles

Il existe actuellement trois règles: toutes, un-typed-import-import et sketchy-null. La règle "Tous" est en réalité le traitement par défaut des erreurs qui n'ont pas de règle plus spécifique. La règle "importation de type non typé" est appelée lorsque vous importez un type à partir d'un fichier non typé. La règle "sketchy-null" est invoquée lorsque vous effectuez un contrôle d'existence sur une valeur pouvant être false ou null / indéfinie. Il existe des règles plus granulaires pour:

  • fragmentaire-null-bool
  • sketchy-null-number
  • sketchy-null-string
  • fragmentaire-nul-mélangé

Niveaux de gravité

Il existe également trois niveaux de gravité: désactivé, avertissement et erreur. Comme vous pouvez l’imaginer, "off" ignore la vérification de type, "avertir" génère des avertissements qui ne provoquent pas la fermeture de la vérification de type et ne s'affichent pas par défaut dans la sortie de la CLI --inclure des avertissements), et "erreur" est gérée exactement comme les erreurs de flux et provoque la sortie du contrôle de type et l'affichage d'un message d'erreur.

Linter avec des arguments de ligne de commande

Utilisez le --des peluches argument de ligne de commande permettant de spécifier plusieurs règles de protection. Par exemple:

flow --lints "all = avertir, untyped-type-import = erreur, sketchy-null-bool = off"

Linting With flowlint Commentaires

Il existe trois types de commentaires: flowlint, flowlint-line et flowlint-next-line.

Le commentaire "flowlint" applique un ensemble de règles dans un bloc jusqu'à ce qu'il soit remplacé par un commentaire correspondant:

type d'importation // import-type-type-typé flowlint: off Foo, Bar, Baz, // import-type-type-typé flowlint: erreur de './untyped.js'; 

S'il n'y a pas de commentaire correspondant, les paramètres s'appliquent simplement jusqu'à la fin du fichier..

La "ligne flowlint" s'applique uniquement à la ligne actuelle:  

function (x:? boolean) if (x) // ligne flowlint-sketchy-null-bool: off… sinon … 

Le "flowlint-next-line" s'applique à la ligne qui suit le commentaire:

function (x:? boolean) // flowlint-next-line sketchy-null-bool: off if (x) … sinon … 

Conclusion

Les grands projets JavaScript développés par de grandes équipes peuvent tirer parti de la vérification de type statique. Il existe plusieurs solutions pour introduire la vérification de type statique dans une base de code JavaScript.. 

JavaScript continue de croître de différentes manières sur le Web. Comme vous pouvez le constater, il n’ya pas que des courbes d’apprentissage, et il existe de nombreux cadres et bibliothèques pour vous occuper. Si vous recherchez des ressources supplémentaires à étudier ou à utiliser dans votre travail, consultez ce que nous avons à votre disposition sur le marché Envato..

Le flux de Facebook est une solution récente et robuste avec une couverture, un outillage et une documentation excellents. Essayez si vous avez une grande base de code JavaScript.