Gjør JavaScript-koden din robust med flyt

JavaScript var alltid et betydelig programmeringsspråk, og er det eneste språket som kjører pålitelig i nettleseren. Nylige trender i front-end-utvikling samt Node.js-basert back-end-utvikling har presset omfanget og kompleksiteten til JavaScript-applikasjoner. 

Store applikasjoner utviklet av store lag kan dra nytte av statisk type kontroll, hvilket vanilje JavaScript mangler. Flow ble utviklet av Facebook for å løse dette problemet. Det er en statisk type kontroller som integreres i utviklingsprosessen, fanger mange problemer tidlig, og hjelper deg med å bevege deg raskt.

Hva er strømmen?

Flow er et verktøy som sjekker din annoterte JavaScript-kode og oppdager ulike problemer som uten at det bare ville oppdages ved kjøretid (eller verre, ikke oppdaget og ødelagt dataene dine). Her er et raskt eksempel.

// //flow funksjon getGreeting (navn: streng): streng retur 'Hei, $ name';  const http = krever ("http"); const greeting = getGreeting ("Gigi") const port = 8888 console.log ('Lytter på port $ port ...') http.createServer (funksjon (forespørsel, svar) response.writeHead (200, "Content Type ":" text / plain "); response.write (hilsen); response.end ();). lytt (port);

Flow vs TypeScript

Før du drar inn i de nitty-gritty detaljene i Flow, er det verdt å sammenligne det med andre alternativer, og spesielt TypeScript. TypeScript er en streng supersett av JavaScript utviklet av Microsoft. Et hvilket som helst JavaScript-program er også et TypeScript-program. 

TypeScript legger til valgfrie annoteringer av typen og generelt tjener samme formål som Flow. Det er imidlertid noen viktige forskjeller. TypeScript er et eget programmeringsspråk som samler til JavaScript, mens Flow annoteringer må fjernes for å komme tilbake til gyldig JavaScript. 

TypeScript har flott verktøy og IDE-støtte. Flow er oppfanget (for eksempel JetBrains WebStorm har innfødt Flow integrasjon).

Den viktigste filosofiske forskjellen er at Flow legger vekt på soliditet. TypeScript 1.0 fikk ikke null feil; TypeScript 2.0 med strenge null sjekker målt opp til Flow i denne forbindelse. Men i andre aspekter som generiske containere eller skrive, er TypeScript mer permissiv og lar ulike kategorier feil gjennom (bare strukturert typing er sjekket, ikke nominell maskinskriving).

TypeScript som sitt eget språk legger til konsepter og språkfunksjoner som klasser, grensesnitt, synlighetsindikatorer (offentlig, privat, lett) og dekoratører. Disse funksjonene gjør det lettere å forstå og bruke for folk som kommer fra vanlige objektorienterte språk som C ++, Java og C #.

Installasjon

Siden Flow annoteringer ikke er standard JavaScript, må de fjernes før du distribuerer programmet. Slik installerer du flyt og flyt-fjern-typer via garn: garn add -dev flytboks flyt-fjerne-typer

Du kan legge til et par skript i package.json-filen din for å automatisere prosessen:

 "scripts": "build": "flyt-fjern-typer src / -d lib /", "prepublish": "garn run build" 

Du bør kjøre prepublish-skriptet før du publiserer koden din til npm-registret.

For andre installasjonsalternativer (for eksempel ved bruk av npm eller babel), sjekk ut installasjonsveiledningen for strømmen.

For å fullføre installasjonen, skriv inn: garn run flow init

Dette vil opprette den nødvendige .flowconfig-filen.

Type system

Flow har to viktige mål: presisjon og hastighet. Typesystemet hans ble utformet for å støtte disse målene.

Presisjon

Presisjon oppnås ved å analysere hvordan koden samhandler med typer, enten merket eller utelatt. En hvilken som helst feilmatch gir en type feil. Annoterte typer støtter nominell skriving, noe som betyr at to forskjellige typer med de samme egenskapene skiller seg fra hverandre og ikke kan erstattes. Typen av en variabel er definert som settet av runtimeverdier variabelen kan motta. 

Hastighet

Strømmen er rask på grunn av en kombinasjon av modularitet og distribuert behandling. Filene analyseres parallelt, og resultatene slås sammen senere via effektiv delt minne for å utføre fullprogramtypekontroll.

Støttede typer

Flow støtter mange typer. I tillegg til primitive typer støtter den også følgende:

  • Gjenstand
  • Array
  • Noen
  • Kan være
  • variabel
  • tuppel
  • Klasse
  • Interface
  • Generisk

Skriv merknader

Flow lar deg deklarere typer samt begrense variabler og parametere til utvalgte verdier:

skriv to2four = 2 | 3 | 4 funksjon doubleIt (nummer: Two2Four) returnummer * 2 console.log (doubleIt (3)) Utgang: 6 

Hvis du overskrider gyldig rekkevidde, får du en feil:

console.log (doubleIt (3)) Output: Feil: src / main.js: 30 30: console.log (doubleIt (5)) // feil ^ nummer. Denne typen er uforenlig med den forventede param-typen på 24: funksjon doubleIt (nummer: Two2Four) ^^^^^^^^ nummer enum Fant 1 feil 

Du kan også definere komplekse typer, inkludert undertyper. I følgende kodeeksempel er krigertypen en undertype av Person. Dette betyr at det er OK å returnere en kriger som en person fra slåss() funksjon. Det er imidlertid forbudt å returnere null.

type person = navn: streng, alder: tall type Warrior = navn: streng, alder: nummer, styrke: tall la redWolf: Warrior = navn: "Red Wolf", alder: 24, styrke: 10 la Skull Crusher: Warrior = navn: "Skull Crusher", alder: 27, styrke: 11 funksjonskamp (w1: Warrior, w2: Warrior): Person if (w1.strength> w2.strength) return w1 w2.strength> w1.strength) return w2 return null Utgang: Fant 1 feil $ flow Feil: src / main.js: 47 47: return null ^^^^ null. Denne typen er inkompatibel med forventet returtype på 39: funksjonskamp (w1: Warrior, w2: Warrior): Person ^^^^^^ objekttype Fant 1 feil 

For å fikse det, la oss returnere den yngre krigen hvis begge krigerne har samme styrke:

funksjonskamp (w1: Warrior, w2: Warrior): Person if (w1.strength> w2.strength) retur w1 hvis (w2.strength> w1.strength) return w2 returnere (w1.age < w2.age ? w1 : w2)  let winner = fight(redWolf, skullCrusher) console.log(winner.name) Output: Skull Crusher 

Flow gir enda mer presis kontroll via klasseutvidelse, invariance, samvariasjon og kontraavvik. Sjekk ut dokumentasjonen for flyt på variansen.

konfigurasjon

Flow bruker .flowconfig konfigurasjonsfilen i rotkatalogen av prosjektene dine. Denne filen inneholder flere seksjoner som lar deg konfigurere hvilke filer Flow skal sjekke og de mange aspektene av operasjonen. 

Inkludere

De [inkludere] delen styrer hvilke kataloger og filer som skal kontrolleres. Rottekatalogen er alltid inkludert som standard. Stiene i [inkludere] seksjoner er relative. En enkelt stjerne er et wild-kort for et filnavn, en utvidelse eller et katalognavn. To stjerner er et wild-kort for enhver dybde av katalog. Her er et eksempel [inkludere] seksjon:

[inkludere] ... /externalFile.js.../ externalDir / ... /otherProject/*.js.../ otherProject / ** / coolStuff /

Overse

De [overse] delen er komplementet til [inkludere]. Filer og kataloger du spesifiserer her, vil ikke bli sjekket av strømmen. Merkelig bruker den en annen syntaks (OCaml-regulære uttrykk) og krever absolutte baner. Endring av dette er på veikart av Flow-teamet.

Inntil da må du huske at inkluderingsseksjonen behandles først, etterfulgt av ignoreringsseksjonen. Hvis du inkluderer og ignorerer samme katalog og / eller fil, blir den ignorert. For å løse problemet med absolutt sti, er det vanlig å prefikse hver linje med .*. Hvis du vil ignorere kataloger eller filer under roten, kan du bruke  plassholder i stedet for .*. Her er et eksempel [overse] seksjon:

[ignorere]. * / __ tester __ /. *. * / src / \ (foo \ | bar \) /.*. * \. ignorere \ .js /ignore_me.js

libs

Enhver ikke-triviell JavaScript-applikasjon bruker mange tredjepartsbiblioteker. Flow kan sjekke hvordan søknaden din bruker disse bibliotekene hvis du gir spesielle libdef-filer som inneholder typen informasjon om disse bibliotekene. 

Flow skanner automatisk "flow-typed" underkatalogen av prosjektet for libdef-filer, men du kan også gi banen til libdef-filer i [libs] -delen. Dette er nyttig hvis du opprettholder et sentralt arkiv av libdef-filer som brukes av flere prosjekter.

Importerer eksisterende typedefinisjoner og lager din egen hvis målbiblioteket ikke oppgir egne definisjoner av type, er ganske enkelt. Se:

  • Flow Documentation: Bibliotek Definisjoner
  • Flow Documentation: Opprette Bibliotek Definisjoner
  • GitHub: Importerer og bruker bibliotekets definisjoner

Lints

Flow har flere lintregler du kan kontrollere og bestemme hvordan du skal behandle dem. Du kan konfigurere reglene fra kommandolinjen, i kodekommentarer, eller i [Lints] delen av konfigurasjonsfilen din. Jeg skal diskutere linting i neste avsnitt, men her er hvordan du konfigurerer den ved hjelp av [Lints] seksjon:

[lint] alle = advarsel untyped-type-import = feil sketchy-null-bool = av

alternativer

De [Options] seksjonen er hvor du forteller Flow hvordan man oppfører seg i en rekke tilfeller som ikke fortjener sin egen seksjon, så de er alle gruppert sammen.

Det er for mange alternativer å liste dem alle her. Noen av de mer interessante er:

  • alle: satt til sann for å sjekke alle filer, ikke bare de med @flow
  • emoji: satt til sann for å legge emojis til statusmeldinger
  • module.use_strict: sett til true hvis du bruker en transpiler som legger til "bruk strenge;"
  • suppress_comment: en regex som definerer en kommentar for å undertrykke eventuelle strømningsfeil på den følgende linjen (nyttig for innledende kode)

Sjekk ut alle alternativene i strømningsveiledningen for å konfigurere alternativer.

Versjon

Strøm og dens konfigurasjonsfilformat utvikler seg. De [versjon] avsnittet kan du spesifisere hvilken versjon av Flow config-filen er utformet for å unngå forvirrende feil.

Hvis versjonen av Flow ikke samsvarer med den konfigurerte versjonen, vil Flow vise en feilmelding.

Her er noen måter å spesifisere de støttede versjonene på:

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

Caret-versjonen holder den første ikke-null-komponenten i versjonen fast. Så ^ 1.2.3 utvider seg til området> = 1.2.3 < 2.0.0, and ^ 0.4.5 ekspanderer til området> = 0,4 < 0.5.0.

Bruke flyt fra kommandolinjen

Flow er et klient-server-program. En Flowserver må kjøres, og klienten kobles til den (eller starter den hvis den ikke kjører). Flow CLI har mange kommandoer og alternativer som er nyttige for vedlikeholds- og introspeksjonsformål, samt for midlertidig å overstyre konfigurasjonen fra .flowconfig.

Typing flyt - hjelp viser alle kommandoene og alternativene. For å få hjelp til en bestemt kommando, skriv inn strømme --hjelp. For eksempel:

$ flow ast --hjelp Bruk: flow ast [OPTION] ... [FILE] f.eks. strømme ast foo.js eller flow 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) 

Viktige kommandoer er:

  • i det: Lag en tom .flowconfig-fil
  • kryss av: gjør en full flytkontroll og skriv ut resultatene 
  • ls: Vis filer som er synlige for Flow
  • status (standard): vis gjeldende flytfeil fra strømningsserveren
  • foreslå: foreslå typer for målfilen

Linting With Flow

Strømmen har et lintingramme som kan konfigureres via .flowconfig-filen som du så tidligere, gjennom kommandolinjearguder eller i kodefiler som bruker flowlint-kommentarer. Alle konfigurasjonsmetoder består av en liste over nøkkelverdige par hvor nøkkelen er en regel og verdien er alvorlighetsgraden. 

regler

Det er for øyeblikket tre regler: alt, untyped-type-import og sketchy-null. Regelen "All" er egentlig standardhåndtering for eventuelle feil som ikke har en mer spesifikk regel. Regelen "untyped-type-import" påberopes når du importerer en type fra en usjiktet fil. Regelen "sketchy-null" påberopes når du gjør eksistens, og kontrollerer en verdi som kan være feil eller null / udefinert. Det er flere granulære regler for:

  • sketchy-null-bool
  • sketchy-null-tall
  • overfladisk-null-streng
  • overfladisk-null-blandet

Alvorlighetsnivåer

Det er også tre alvorlighetsgrader: av, advarsel og feil. Som du kan tenke deg, "off" hopper av typen kontroll, "advarsel" produserer advarsler, som ikke forårsaker at type-sjekken avslutter og ikke vises som standard i CLI-utgangen (du kan se dem med --inkludere-advarsler), og "feil" håndteres akkurat som strømningsfeil og forårsaker at typekontrollen avslutter og viser en feilmelding.

Linting Med Command-Line Argumenter

Bruke --Lints kommandolinjeparametre for å angi flere lintregler. For eksempel:

flyt - linjer "alle = advarsel, untyped-type-import = feil, sketchy-null-bool = off"

Linting med flowlint Kommentarer

Det finnes tre typer kommentarer: flowlint, flowlint-line og flowlint-next-line.

"Flowlint" -kommentaren gjelder et sett med regler i en blokk til det er overstyrt av en matchende kommentar:

importtype // flowlint untyped-type-import: av Foo, Bar, Baz, // flowlint untyped-type-import: error fra './untyped.js'; 

Hvis det ikke er noen matchende kommentar, gjelder innstillingene bare til slutten av filen.

"Flowlint-linjen" gjelder bare for den nåværende linjen:  

funksjon (x:? boolean) if (x) // flowlint-line sketchy-null-bool: off ... else ... 

"Flowlint-next-line" gjelder linjen som følger kommentaren:

funksjon (x:? boolean) // flowlint-next-line sketchy-null-bool: av hvis (x) ... annet ... 

Konklusjon

Store JavaScript-prosjekter utviklet av store lag kan ha stor nytte av statisk kontroll. Det finnes flere løsninger for å introdusere statisk type sjekker inn i en JavaScript-kodebase. 

JavaScript fortsetter å vokse på en rekke måter på nettet. Det er ikke uten sine lærekurver, og det er mange rammer og biblioteker som holder deg opptatt, som du kan se. Hvis du leter etter flere ressurser for å studere eller bruke i arbeidet ditt, sjekk ut hva vi har tilgjengelig på Envato-markedet.

Facebook's Flow er en nylig og robust løsning med utmerket dekning, verktøy og dokumentasjon. Gi det en prøve hvis du har en stor JavaScript-kodebase.