Нежно запознаване с TypeScript декоратори

Демистифицирайте този мощен модел, като изградите декоратори от нулата

Снимка на Cederic X на Unsplash

Декораторите са една от най-мощните функции, които Typescript може да предложи, позволявайки ни да разширим функционалността на класове и методи по чист и декларативен начин. Понастоящем декораторите са предложение за етап 2 за JavaScript, но вече придобиха популярност в екосистемата TypeScript, като се използват от водещи проекти с отворен код като Angular и Inversify.

Колкото и страхотни да са декораторите, разбирането на начина, по който те действат, може да е умопомрачително. В тази статия се стремя да ви дам добро разбиране на декораторите за по-малко от 5 минути от вашето време. И така, какви са тези декоратори изобщо?

Декораторите са просто чист синтаксис за увиване на парче код с функция

Декораторите са експериментална характеристика, така че детайлите за внедряване могат да се променят в бъдеще, но основните принципи са вечни. За да позволите използването на декоратори, добавете "експериментални декоратори": true към опциите на вашия компилатор във файл tsconfig.json и се уверете, че вашата цел на транспилация е ES5 или по-нова версия.

Добре, часовникът тиктака, така че нека да кодираме!

Пътуването започва с класните декоратори

Кажете, че имате бизнес, който отдава стари замъци на мощни семейства и работите върху създаването на HTTP сървър. Решихте да изградите всяка крайна точка на вашия API като клас и публичните методи на класа ще съответстват на HTTP методите. Това може да изглежда нещо подобно:

Това е хубаво начало и сега се нуждаем от прост начин да „регистрираме“ всеки от тези класове като крайна точка в нашия HTTP сървър. Нека създадем проста функция, за да се погрижим за това. Нашата функция ще получи клас като аргумент и ще добави екземпляр от този клас като крайна точка към нашия сървър. Така:

Без да забележите, вече написахме първия си декоратор! Точно така, просто е толкова лесно. Всичко, което е декоратор, е функция, която приема клас като аргумент и тук го имаме. Сега, вместо да извикаме registerEndpoint по "редовен" начин, можем просто да украсим нашите класове с @registerEndpoint. не ми вярваш? Погледни:

Първият ни декоратор стартирахме и ни отне само 2 минути. Вече сме готови да се потопим по-дълбоко и да разгърнем силата на метода декоратор.

Разгърнете силата на метода декоратор

Нека да кажем, че искаме да защитим някои от нашите крайни точки, така че само удостоверени потребители да имат достъп до тях. За целта можем да създадем нов декоратор, наречен защита. Засега всичко, което нашият декоратор ще направи, е да добави защитения метод към масив, наречен protectedMethods.

Както можете да видите, методът декоратор взема 3 аргумента:

  1. target - Прототипът на нашия клас (или конструктора на класа, ако декорираният метод е статичен).
  2. propertyKey - Името на декорирания метод.
  3. дескриптор - Обект, който съдържа украсената функция и някои метаданни по отношение на нея.

Засега четем само информация относно класовете и методите, които украсихме, но истинското забавление започва, когато започнем да променяме тяхното поведение. Можем да направим това, като просто върнем стойност от декоратора. Когато декоратор на метод върне стойност, тази стойност ще се използва вместо оригиналния дескриптор (който държи оригиналния метод).

Нека да го изпробваме, като създадем декоратор, наречен nope, който замества оригиналния ни метод с метод, който отпечатва „nope“ винаги, когато е извикан. За да направя това, ще превъзмогна дескриптора.value, където се съхранява оригиналната функция, с моята функция:

До този момент си играхме с основите на декораторите на методи, но все още не сме създали нищо полезно. Това, което планирам да направя по-нататък, е да пренапиша декоратора за защита, но този път, вместо да регистрира само имената на декорираните методи, той всъщност ще блокира неоторизирани заявки.

Следващата стъпка ще бъде малко по-сложна от последните, така че понасяйте с мен. Ето стъпките, които трябва да предприемем:

  1. Извадете оригиналната функция от дескриптора и я съхранявайте някъде другаде за по-късна употреба.
  2. Замени descript.value с нова функция, която приема същите аргументи като оригинала.
  3. В рамките на новата ни функция проверете дали заявката е автентифицирана и ако не изведе грешка.
  4. И накрая, също в рамките на новата ни функция, вече можем да извикаме оригиналната функция с необходимите аргументи, да уловим нейната възвръщаема стойност и да я върнем.

Невероятно! Разполагаме с напълно оперативен декоратор за защита. Сега добавянето или премахването на защита от нашите методи е парче торта.

Обърнете внимание как в ред 8 свързваме оригиналната функция за това, така че тя ще има достъп до инстанцията на своя клас. Например, без този ред методът get () няма да може да чете този дом.

Изминахме доста път, но пред нас има още. В този момент ви насърчавам да отделите малко време и да се уверите, че разбирате всеки момент от това, което сме направили досега. За да ви улесня, сложих целия код по-горе в детската площадка, за да можете да го пуснете, промените и да го счупите, докато усетите, че напълно го получавате.

Спечелете повече мощност с декоративни фабрики

Да речем, че сега искаме да добавим нова крайна точка, за да върнем членовете на семейство Старк, по пътя / семейства / старци / членове. Е, очевидно не можем да създадем клас с това име, така че какво ще правим?

Това, от което се нуждаем тук, е начин да предадем параметри, които ще диктуват поведението на нашата декораторска функция. Нека разгледаме още един добър добър стар декоратор на регистър:

За да изпратим параметри до нашия декоратор, трябва да го трансформираме от обикновен декоратор към фабрика за декоратори. Фабрика за декоратори е функция, която връща декоратор. За да го направим, всичко, което трябва, е да увием нашия оригинален декоратор, като този:

Сега също можем да увием защитния си декоратор, така че той ще получи очаквания маркер като параметър:

заключение

На този етап добре разбирате декораторите, как работят, както и силата и изразителността, които ни позволяват като програмисти. В тази статия разгледах най-полезните и често срещани техники, но има още много да научите. Декораторите в Typescript могат да се прилагат не само за класове и методи, но и за свойства на класове и аргументи на метод. Надявам се, че с вашето новопридобито разбиране за декораторите, ще можете лесно да го вземете от документацията. Както винаги, поставям целия код на тази статия в детската площадка, така че продължете напред и играйте!

да, ти го направи!

Ако ви е харесала тази статия, не се колебайте да я ръкопляскате, така че повече хора ще я намерят и ще й харесат, а ако искате да видите още неща, които пиша, можете да ме последвате. Кажете ми в коментарите, ако имате въпроси.

Освен това може да искате да разгледате и другите ми статии в TypeScript относно генеричните данни и разширенията или за дизайна на класове.