En blid introduktion til TypeScript-dekoratører

Afmystificer dette kraftfulde mønster ved at bygge dekoratører fra bunden

Foto af Cederic X på Unsplash

Dekoratører er en af ​​de mest kraftfulde funktioner, som Typescript har at tilbyde, så vi kan udvide funktionaliteten af ​​klasser og metoder på en ren og erklærende måde. Dekoratører er i øjeblikket et trin 2-forslag til JavaScript, men har allerede vundet popularitet i TypeScript-økosystemet, der bruges af førende open source-projekter som Angular og Inversify.

Men det kan være fantastisk dekoratører, at forstå, hvordan de handler, måske er sjovt. I denne artikel har jeg til formål at give dig en solid forståelse af dekoratører på mindre end 5 minutter af din tid. Så hvad er disse dekoratører alligevel?

Dekoratører er bare en ren syntaks til indpakning af et stykke kode med en funktion

Dekoratører er en eksperimentel funktion, så implementeringsdetaljer kan ændre sig i fremtiden, men de underliggende principper er evige. For at tillade brugen af ​​dekoratører tilføj "eksperimentelle dekoratorer": sandt til dine kompilatorindstillinger i tsconfig.json-fil, og sørg for, at dit transpilationsmål er ES5 eller nyere.

Okay, uret tikker, så lad os få kodning!

Rejsen begynder med klassedekoratører

Lad os sige, at du har en virksomhed, der lejer gamle slotte til magtfulde familier, og du arbejder med at oprette en HTTP-server. Du besluttede at opbygge hvert slutpunkt i dit API som en klasse, og klassens offentlige metoder svarer til HTTP-metoderne. Dette ser måske sådan ud:

Det er en dejlig start, og nu har vi brug for en enkel måde at “registrere” hver af disse klasser som et endepunkt på vores HTTP-server. Lad os oprette en simpel funktion til at tage sig af det. Vores funktion får en klasse som et argument og tilføjer en forekomst af den klasse som et endepunkt til vores server. Ligesom:

Uden at du bemærker det, skrev vi allerede vores første dekoratør! Det er rigtigt, det er så enkelt som det. Alt, hvad en dekoratør er, er en funktion, der tager en klasse som et argument, og her har vi det. I stedet for at kalde registerEndpoint på den "almindelige" måde, kan vi bare dekorere vores klasser med @registerEndpoint. tror du ikke på mig? Se:

Vi fik vores første dekoratør i gang, og det tog os kun 2 minutter. Vi er nu klar til at dykke dybere og løsne kraften i metodedekoratøren.

Slip løs kraften i metodedekoratøren

Lad os sige, at vi ønsker at beskytte nogle af vores slutpunkter, så kun godkendte brugere kan få adgang til dem. For at gøre det kan vi oprette en ny dekoratør kaldet beskytte. For øjeblikket vil alt vores dekoratør gøre, at tilføje den beskyttede metode til en matrix, der kaldes protectionMethods.

Som du kan se, tager metoden dekoratøren 3 argumenter:

  1. mål - Prototypen af ​​vores klasse (eller konstruktøren af ​​klassen, hvis den dekorerede metode er statisk).
  2. propertyKey - Navnet på den dekorerede metode.
  3. deskriptor - Et objekt, der indeholder den dekorerede funktion og nogle metadata vedrørende den.

Indtil videre læser vi kun information om de klasser og metoder, vi dekorerede, men den virkelige sjov begynder, når vi begynder at ændre deres opførsel. Vi kan gøre det ved blot at returnere en værdi fra dekoratøren. Når en metodedekorator returnerer en værdi, bruges denne værdi i stedet for den originale deskriptor (som indeholder den originale metode).

Lad os prøve det ved at oprette en dekoratør kaldet nope, der erstatter vores originale metode med en metode, der udskriver "nope", når det kaldes. For at gøre dette vil jeg tilsidesætte descriptor.value, som er, hvor den originale funktion er gemt, med min funktion:

På dette tidspunkt spillede vi rundt med det grundlæggende for metodekunstnere, men har ikke skabt noget nyttigt endnu. Det, jeg planlægger at gøre næste, er at omskrive beskyttelsesindretningen, men denne gang i stedet for kun at logge navnene på de dekorerede metoder, vil det faktisk blokere uautoriserede anmodninger.

Dette næste trin vil være lidt mere kompliceret fra de sidste, så bær med mig. Her er de trin, vi skal tage:

  1. Uddrag den originale funktion fra deskriptoren, og opbevar den et andet sted til senere brug.
  2. Overstyr descriptor.value med en ny funktion, der tager de samme argumenter som originalen.
  3. I vores nye funktion skal du kontrollere, om anmodningen er godkendt, og hvis ikke kast en fejl.
  4. Endelig, også inden for vores nye funktion, kan vi nu kalde den originale funktion med de argumenter, den har brug for, fange dens returneringsværdi og returnere den.

Fantastiske! Vi har en fuldt operationel beskytte dekoratør. Nu tilføjes eller fjernes beskyttelse fra vores metoder er et stykke kage.

Bemærk, hvordan vi i linje 8 binder den originale funktion til denne, så den får adgang til forekomsten af ​​sin klasse. Uden denne linje kan vores get () -metode f.eks. Ikke være i stand til at læse denne.huse.

Vi er gået ret, men der er mere foran os. På dette tidspunkt opfordrer jeg dig til at tage et øjeblik og sikre dig, at du forstår alt hvad vi har gjort indtil videre. For at gøre det lettere for dig lægger jeg al koden ovenfor på legepladsen her, så du kan køre den, ændre den og bryde den, indtil du føler, at du fuldt ud får den.

Få mere magt med dekoratørfabrikker

Lad os sige, at vi nu ønsker at tilføje et nyt slutpunkt for at returnere Stark-familiemedlemmer, på stien / familier / stark / medlemmer. Vi kan naturligvis ikke oprette en klasse med det navn, så hvad skal vi gøre?

Det, vi har brug for her, er en måde at videregive parametre, der dikterer opførslen af ​​vores dekoratørfunktion. Lad os tage et nyt kig på vores gode gamle registerEndpoint dekoratør:

For at sende parametre til vores dekoratør er vi nødt til at omdanne det fra en almindelig dekoratør til en dekoratørfabrik. En dekoratørfabrik er en funktion, der returnerer en dekoratør. For at fremstille en er alt, hvad vi har brug for, at pakke vores originale dekoratør på denne måde:

Nu kan vi også pakke vores beskyttende dekoratør ind, så det får det forventede token som en parameter:

Konklusion

På dette tidspunkt har du en god forståelse af dekoratører, hvordan de fungerer, samt kraften og udtryksevnen, de tillader os som programmerere. I denne artikel dækkede jeg de mest nyttige og mest almindelige teknikker, men der er meget mere at lære. Dekoratører i typeskrift kan ikke kun anvendes til klasser og metoder, men også til egenskaber ved klasser og metodargumenter. Jeg håber, at med din nyligt erhvervede forståelse af dekoratører, vil du være i stand til let at hente den ud af dokumentationen. Som altid lægger jeg al denne artikels kode på legepladsen, så gå videre og leg!

yay, du gjorde det!

Hvis du har haft glæde af denne artikel, er du velkommen til at klappe for den, så flere mennesker finder den og nyder godt af, og hvis du ønsker at se flere af de ting, jeg skriver, er du velkommen til at følge mig. Fortæl mig det i kommentarerne, hvis du har spørgsmål.

Det kan også være en god ide at tjekke mine andre TypeScript-artikler om generika og augmentation eller om klassedesign.