TypeScript je programski jezik sa strogim tipovima, nadograđen na JavaScript, koji vam pruža naprednije alate u razvojnom procesu. TypeScript je razvijen kako bi se prevazišli određeni izazovi koji se javljaju prilikom kodiranja u JavaScriptu. Glavna prednost TypeScripta leži u upotrebi tipova, što značajno smanjuje potencijalne greške.
U TypeScript kodu, svaka vrednost poseduje specifičan tip. TypeScript vrši proveru usklađenosti svake vrednosti sa pravilima definisanim za njen tip. Ovo omogućava detekciju grešaka u kodu pre njegovog izvršavanja, čime se izbegavaju problemi koji se mogu javiti u runtime-u.
Ovaj proces se naziva statička provera tipa, koja podrazumeva otkrivanje grešaka u fazi razvoja na osnovu tipova vrednosti koje se koriste u programu.
Pored pomoći u pisanju jasnijeg i razumljivijeg koda, kao i statičke provere tipa, TypeScript nudi dodatne funkcije koje olakšavaju čitljivost, ponovnu upotrebu i održavanje koda. Jedna od tih funkcija su TypeScript dekoratori.
TypeScript Dekoratori
Dekoratori u TypeScriptu su funkcije koje omogućavaju modifikaciju ili poboljšanje ponašanja koda tokom izvršavanja, kao i dodavanje metapodataka kodu. Dekoratori omogućavaju metaprogramiranje u TypeScriptu, što je tehnika u kojoj programi mogu tretirati druge programe kao svoje podatke i na taj način menjati njihovo ponašanje.
U osnovi, dekoratori su funkcije koje se pozivaju kako bi izvršile određenu logiku tokom izvršavanja, kada se pristupi dekorisanim elementima ili kada se oni modifikuju.
Na ovaj način, dekorisanim elementima se može dodati dodatna funkcionalnost. TypeScript dekoratori se mogu primeniti na deklaracije klasa, metoda, svojstava, pristupa (getter-i i setter-i) i parametre metoda.
U TypeScriptu, dekoratori imaju prefiks @ simbola i imaju oblik @izraza, pri čemu se izraz procenjuje kao funkcija koja će biti pozvana tokom izvršavanja. Opšta sintaksa za upotrebu dekoratora u TypeScriptu je sledeća:
@decoratorName itemToDecorate
Primer jednostavnog dekoratora klase je prikazan u nastavku:
function logClass(target: Function) { console.log("Dekorator klase 'logClass' je pozvan"); console.log("Klasa:", target); } @logClass // @logClass je dekorator class MyClass { constructor() { console.log("Kreirana je instanca klase MyClass"); } } const myInstance = new MyClass();
Rezultat izvršavanja gornjeg koda je:
Izlaz:
Dekorator klase 'logClass' je pozvan Klasa: [class MyClass] Kreirana je instanca klase MyClass
Funkcija `logClass()` prihvata jedan argument, koji se naziva `target` i ima tip `Function`. Argument `target` je tipa `Function` jer će primiti konstruktor klase koju dekorišemo.
Da bismo koristili `logClass()` kao dekorator za dekorisanje klase `MyClass`, stavljamo `@logClass` neposredno pre deklaracije `MyClass`. Dekorator mora imati isto ime kao funkcija koju želite da koristite za dekorisanje elementa.
Kada se kreira instanca `MyClass`, ponašanje dekoratora se izvršava pored konstruktora klase, kao što je prikazano na izlazu.
Dekoratori su trenutno dostupni u TypeScriptu kao eksperimentalna funkcija. Zbog toga, da biste koristili dekoratore u TypeScriptu, potrebno je da omogućite `experimentalDecorators` u opcijama kompajlera u datoteci `tsconfig.json`.
Da biste to uradili, generišite datoteku `tsconfig.json` u folderu vašeg TypeScript projekta izvršavanjem sledeće komande u terminalu otvorenom u direktorijumu vašeg projekta:
tsc --init
Kada dobijete datoteku `tsconfig.json`, otvorite je i uklonite komentare ispred `experimentalDecorators` kao što je prikazano u nastavku:
Pored toga, podesite JavaScript ciljnu verziju na najmanje ES2015.
Važnost TypeScript Dekoratora
Kvalitetan kod se lako može prepoznati po tome koliko je kod čitljiv, upotrebljiv i održiv. Čitljiv kod je kod koji je lak za razumevanje i interpretaciju i jasno prenosi nameru programera onome ko čita kod.
Kod za višekratnu upotrebu, sa druge strane, je kod koji omogućava da se određene komponente, kao što su funkcije i klase, ponovo koriste, prilagođavaju i koriste u drugim delovima aplikacije ili u potpuno novim aplikacijama bez značajnih modifikacija.
Održiv kod je kod koji se lako može modifikovati, ažurirati i popraviti tokom svog životnog veka.
TypeScript dekoratori vam omogućavaju da postignete čitljivost koda, ponovnu upotrebu i održivost. Prvo, TypeScript dekoratori omogućavaju da poboljšate ponašanje vašeg koda koristeći deklarativnu sintaksu koja je lakša za čitanje. Možete inkapsulirati logiku u dekoratore i pozvati ih dekorišući različite elemente vašeg koda tamo gde vam je logika potrebna.
Ovo čini vaš kod lakim za čitanje i razumevanje šta se dešava. Dekoratori jasno prenose nameru programera.
Dekoratori nisu elementi za jednokratnu upotrebu; oni su po prirodi za višekratnu upotrebu. Možete kreirati dekorator jednom i koristiti ga više puta u više oblasti.
Stoga, možete definisati dekoratore, uvesti ih i koristiti bilo gde u bazi koda gde želite da izmenite ponašanje svog koda. Ovo je korisno jer vam omogućava da izbegnete dupliranje logike u vašoj bazi koda, čime se povećava mogućnost ponovne upotrebe koda.
Dekoratori vam takođe daju veliku dozu fleksibilnosti i modularnosti u kodu, omogućavajući vam da razdvojite različite funkcionalnosti u nezavisne komponente. Ovo, zajedno sa činjenicom da dozvoljavaju pisanje čitljivog i koda za više puta, znači da će TypeScript dekoratori omogućiti da imate kod koji je jednostavan za održavanje.
Tipovi TypeScript Dekoratora
Kao što je ranije pomenuto, TypeScript dekoratori mogu biti povezani sa klasama, svojstvima klasa, metodama klasa, pristupima klasa i parametrima metoda klase. Od elemenata koje možemo ukrasiti, dobijamo različite tipove TypeScript dekoratora. Ovi dekoratori uključuju:
#1. Dekorator Klase
Dekorator klase je dekorator koji se koristi za posmatranje, modifikovanje ili zamenu definicije klase. Proglašava se neposredno pre klase koju dekoriše. Dekorator klase se primenjuje na konstruktor klase koju dekoriše. Tokom izvršavanja, dekorator klase će biti pozvan sa konstruktorom klase koju dekoriše kao jedinim argumentom.
Dekorator klase koji se koristi za sprečavanje proširenja klase prikazan je u nastavku:
function frozen(target: Function) { Object.freeze(target); Object.freeze(target.prototype) } @frozen class Vehicle { wheels: number = 4; constructor() { console.log("Vozilo je kreirano") } } class Car extends Vehicle { constructor() { super(); console.log("Automobil je kreiran"); } } console.log(Object.isFrozen(Vehicle));
Da bismo sprečili proširenje klase, koristimo funkciju `Object.freeze()` i prosleđujemo joj klasu koju želimo da zamrznemo. Dekorator se koristi za dodavanje ove funkcionalnosti klasi. Možemo proveriti da li je klasa `Vehicle` zamrznuta tokom izvršavanja tako što ćemo je proslediti u `isFrozen()`, izlaz koda je prikazan ispod:
true
#2. Dekorator Svojstva
Dekorator svojstava se koristi za dekorisanje svojstva klase i deklariše se neposredno pre dekorisanja svojstva. Dekoratori svojstava se mogu koristiti za modifikaciju ili posmatranje definicije svojstva.
Tokom izvršavanja, dekorator će biti pozvan i prihvatiće dva argumenta. Prvo, funkciju konstruktora klase ako je član statičan, ili prototip klase u slučaju da je član instance. Drugi argument je ime člana, odnosno svojstva koje dekorišete.
U TypeScriptu, statički članovi imaju ključnu reč `static` ispred sebe. Statičkim članovima se može pristupiti bez instanciranja klase. Članovi instance nemaju ključnu reč `static` ispred sebe i može im se pristupiti samo nakon što je instanca klase kreirana.
Primer dekoratora svojstva je prikazan u nastavku:
function wheelsDecorator(target: any, propertyName: string) { console.log(propertyName.toUpperCase()) } class Vehicle { @wheelsDecorator wheels: number = 4; constructor() { console.log("Vozilo je kreirano") } }
Rezultat pokretanja koda je prikazan u nastavku:
WHEELS
#3. Dekorator Metode
Dekorator metode, deklarisan neposredno pre deklaracije metode, je dekorator koji se koristi za posmatranje, modifikovanje ili zamenu definicije metode. Prihvata tri argumenta, funkciju konstruktora klase u slučaju da je član statičan, ili prototip klase ako je član instance.
Drugi argument je ime člana, i, konačno, deskriptor svojstva za člana. Deskriptor svojstva je objekat povezan sa svojstvima objekta i pruža informacije o atributima i ponašanju svojstva.
Dekoratori metoda su korisni kada želite da izvršite neku radnju pre ili posle pozivanja metode. Takođe ih možemo koristiti za evidentiranje informacija o metodi koja se poziva. Ovo može biti korisno u slučaju da želite da obavestite korisnika da je metoda zastarela; to jest, i dalje je dostupna za upotrebu, ali se ne preporučuje da je koristite jer se kasnije može ukloniti.
Primer dekoratora metoda je prikazan u nastavku:
const logDeprecated =(target: any, methodName: string, descriptor: PropertyDescriptor) => { console.log(`${methodName} je zastarela`) console.log(descriptor); } class Vehicle { wheels: number = 4; constructor() { console.log("Vozilo je kreirano") } @logDeprecated reFuel(): void { console.log("Vozilo se puni gorivom"); } }
Izlaz:
reFuel je zastarela { value: [Function: reFuel], writable: true, enumerable: false, configurable: true }
#4. Dekoratori Pristupa
U TypeScriptu postoje dve vrste metoda pristupa, `get` i `set`. Metode pristupa se koriste za kontrolu pristupa svojstvima klase. Dekoratori pristupa se koriste za dekorisanje ove dve metode pristupa i deklarišu se neposredno pre deklaracije pristupa. Pošto su pristupi i dalje metode, dekoratori pristupa rade isto kao i dekoratori metoda.
Primer dekoratora pristupa je prikazan u nastavku:
const logWheels =(target: any, accessorName: string, descriptor: PropertyDescriptor) => { console.log(`${accessorName} se koristi za dobijanje broja točkova`) console.log(descriptor); } class Vehicle { private wheels: number = 4; constructor() { console.log("Vozilo je kreirano") } @logWheels get numWheels(): number { return this.wheels; } }
Izlaz:
numWheels se koristi za dobijanje broja točkova { get: [Function: get numWheels], set: undefined, enumerable: false, configurable: true }
Kod dekoratora pristupa, važno je napomenuti da se dekoratori ne mogu primeniti na više pristupa za dobijanje/setovanje istog imena. Na primer, u našem primeru koda iznad, ako kreirate `set numWheels`, ne možete koristiti dekorator `logWheels` na njemu.
#5. Dekoratori Parametara
Dekorator parametara se koristi da bi se primetilo da je parametar deklarisan u metodi i deklariše se pre deklaracije parametra. Dekoratori parametara prihvataju tri argumenta, prvo, funkciju konstruktora klase za statički član ili prototip klase za člana instance.
Drugi argument je ime člana, odnosno ime parametra. Treći argument je redni indeks parametra u listi parametara funkcije. To jest, u listi parametara, na kojoj poziciji je parametar, pri čemu je prvi parametar na indeksu 0?
Primer dekoratora parametara je prikazan u nastavku:
const passengerLog = (target: Object, propertyKey: string, parameterIndex: number) => { console.log(`Dekorator na parametru ${propertyKey} na indeksu ${parameterIndex}`); } class Vehicle { private wheels: number = 4; constructor() { console.log("Vozilo je kreirano") } pickPassenger( location: string, numPassengers: string, @passengerLog driver: string) { console.log(`${numPassengers} pokupljen na lokaciji ${location} od strane vozača ${driver}`) } dropPassenger(driver: string, @passengerLog location: string, numPassengers: string) { console.log(`${numPassengers} iskrcan na lokaciji ${location} od strane vozača ${driver}`) } }
Izlaz:
Dekorator na parametru pickPassenger na indeksu 2 Dekorator na parametru dropPassenger na indeksu 1
Zaključak
TypeScript dekoratori znatno poboljšavaju čitljivost vašeg koda i pomažu vam da napišete modularan kod za više puta, jer dekoratore možete deklarisati jednom i koristiti ih mnogo puta. Pored toga, dekoratori doprinose ukupnoj održivosti vašeg koda.
Iako su još uvek eksperimentalna funkcija, dekoratori su veoma korisni i svakako biste trebali razmisliti o tome da se upoznate sa njima.
Takođe možete pročitati kako da konvertujete string u broj u TypeScriptu.