TypeScript je silně typovaný programovací jazyk, který vychází z JavaScriptu a poskytuje rozsáhlejší nástroje pro vývoj. Jeho cílem je eliminovat problémy, které se objevují při programování v JavaScriptu. Klíčem k tomu jsou právě typy, které TypeScript zavádí.
Každá hodnota v kódu TypeScriptu má svůj určený typ. TypeScript ověřuje, zda všechny hodnoty splňují pravidla daného typu, čímž se odhalí chyby ještě před spuštěním programu.
Tento proces se nazývá statická typová kontrola. Díky ní se chyby v kódu odhalují již během vývoje, na základě typů použitých hodnot.
Kromě zvýšené čitelnosti a statické typové kontroly, TypeScript nabízí i další funkce, které zlepšují čitelnost, znovupoužitelnost a udržovatelnost kódu. Jednou z takových funkcí jsou dekorátory.
Dekorátory TypeScript
Dekorátory v TypeScriptu umožňují modifikovat chování kódu za běhu nebo přidávat metadata. Představují formu metaprogramování, kde programy mohou manipulovat s jinými programy a ovlivňovat tak jejich chování.
Dekorátory jsou v podstatě funkce, které se spouštějí za běhu při přístupu k dekorovaným prvkům nebo při jejich úpravě.
Tímto způsobem se k těmto prvkům přidávají další funkce. Dekorátory v TypeScriptu se mohou aplikovat na deklarace tříd, metody, vlastnosti, gettery/settery a parametry metod.
V TypeScriptu mají dekorátory předponu @
a mají formu @expression
, kde expression
se vyhodnotí na funkci, která se volá za běhu. Obecná syntaxe pro použití dekorátorů je:
@názevDekorátoru prvekKterýSeDekoruje
Následuje příklad jednoduchého dekorátoru třídy:
function logClass(target: Function) { console.log("Byl zavolán dekorátor třídy Log"); console.log("Třída:", target); } @logClass // @logClass je dekorátor class MojeTrida { constructor() { console.log("Byla vytvořena instance třídy MojeTrida"); } } const mojeInstance = new MojeTrida();
Výsledek spuštění tohoto kódu je:
Výstup:
Byl zavolán dekorátor třídy Log Třída: [class MojeTrida] Byla vytvořena instance třídy MojeTrida
Funkce logClass()
přijímá jeden argument target
typu Function
, protože dostává konstruktor třídy, kterou dekorujeme.
Pro použití logClass()
jako dekorátoru pro třídu MojeTrida
, umístíme @logClass
těsně před deklaraci MojeTrida
. Dekorátor musí mít stejný název jako funkce, která se má použít k dekorování prvku.
Při vytvoření instance MojeTrida
, se kromě konstruktoru třídy provede i logika dekorátoru, jak je vidět z výstupu.
Dekorátory jsou v současné době v TypeScriptu experimentální funkcí. Proto je nutné v souboru tsconfig.json
povolit experimentalDecorators
, aby bylo možné dekorátory používat.
Soubor tsconfig.json
se vygeneruje pomocí příkazu v terminálu:
tsc --init
Po vytvoření souboru tsconfig.json
, otevřete ho a odkomentujte experimentalDecorators
:
Kromě toho je potřeba nastavit cílovou verzi JavaScriptu alespoň na ES2015.
Význam dekorátorů TypeScript
Kvalitní kód se pozná podle jeho čitelnosti, znovupoužitelnosti a udržovatelnosti. Čitelný kód je snadno pochopitelný a jasně vyjadřuje záměr vývojáře.
Znovupoužitelný kód umožňuje opětovné použití komponent, jako jsou funkce a třídy, v jiných částech aplikace, nebo v úplně nové aplikaci. Udržovatelný kód lze snadno upravovat, aktualizovat a opravovat během jeho životnosti.
Dekorátory TypeScript umožňují dosáhnout čitelnosti, znovupoužitelnosti a udržovatelnosti kódu. Umožňují vylepšit chování kódu pomocí deklarativní syntaxe, která je snáze čitelná. Logiku lze zapouzdřit do dekorátorů a vyvolávat je dekorováním různých prvků kódu.
Dekorátory jasně vyjadřují záměr vývojáře a usnadňují pochopení kódu.
Dekorátory nejsou určené pro jedno použití; jsou přirozeně opakovaně použitelné. Dekorátor se definuje jednou a může se opakovaně používat v různých oblastech.
Dekorátory lze definovat, importovat a použít kdekoli v kódové základně. To umožňuje vyhnout se duplikaci logiky a zvyšuje znovupoužitelnost kódu.
Dekorátory poskytují flexibilitu a modularitu a umožňují oddělit různé funkce do nezávislých komponent. Díky nim je kód čitelnější, znovupoužitelný a snadno udržovatelný.
Typy dekorátorů TypeScript
Dekorátory TypeScript lze aplikovat na třídy, vlastnosti, metody, accessory (gettery a settery) a parametry metod. Podle toho, na jaký element se dekorátor aplikuje, získáme různé typy dekorátorů.
#1. Dekorátor třídy
Dekorátor třídy slouží k modifikaci definice třídy. Deklaruje se těsně před třídou, kterou dekoruje. Aplikuje se na konstruktor třídy a za běhu se volá s jediným argumentem, kterým je konstruktor třídy.
Příklad dekorátoru třídy, který zabraňuje rozšíření třídy:
function frozen(target: Function) { Object.freeze(target); Object.freeze(target.prototype) } @frozen class Vozidlo { kola: number = 4; constructor() { console.log("Bylo vytvořeno vozidlo") } } class Auto extends Vozidlo { constructor() { super(); console.log("Bylo vytvořeno auto"); } } console.log(Object.isFrozen(Vozidlo));
Funkce Object.freeze()
se používá k zabránění rozšíření třídy. Dekorátor slouží k přidání této funkce do třídy. Funkce isFrozen()
se používá k ověření, zda je třída zmrazena. Výstup kódu je:
true
#2. Dekorátor vlastnosti
Dekorátor vlastnosti slouží k dekorování vlastnosti třídy a deklaruje se těsně před danou vlastností. Dekorátory vlastností se používají k modifikaci definice vlastnosti.
Dekorátor se volá za běhu se dvěma argumenty. První je konstruktor třídy (pokud je člen statický), nebo prototyp třídy (pokud se jedná o instanční člen). Druhý argument je název vlastnosti.
V TypeScriptu mají statické členy klíčové slovo static
. Statické členy jsou dostupné bez nutnosti vytvářet instanci třídy. Instanční členové nemají static
a lze k nim přistupovat až po vytvoření instance třídy.
Příklad dekorátoru vlastnosti:
function kolaDekorator(target: any, propertyName: string) { console.log(propertyName.toUpperCase()) } class Vozidlo { @kolaDekorator kola: number = 4; constructor() { console.log("Bylo vytvořeno vozidlo") } }
Výstup spuštění kódu:
KOLA
#3. Dekorátor metody
Dekorátor metody, deklarovaný těsně před deklarací metody, slouží k pozorování, úpravě nebo nahrazení definice metody. Má tři argumenty: konstruktor třídy (pro statický člen), nebo prototyp třídy (pro instanční člen).
Druhým argumentem je název metody a třetím je popisovač vlastnosti (property descriptor). Popisovač vlastnosti je objekt s informacemi o atributech a chování vlastnosti.
Dekorátory metod se hodí pro provedení nějaké akce před nebo po zavolání metody. Lze je také použít k logování informací o volané metodě, nebo k upozornění, že metoda je zastaralá.
Příklad dekorátoru metody:
const logZastarale = (target: any, methodName: string, descriptor: PropertyDescriptor) => { console.log(`${methodName} je zastaralá`); console.log(descriptor); } class Vozidlo { kola: number = 4; constructor() { console.log("Bylo vytvořeno vozidlo") } @logZastarale natankuj(): void { console.log("Vaše vozidlo se tankuje"); } }
Výstup:
natankuj je zastaralá { value: [Function: natankuj], writable: true, enumerable: false, configurable: true }
#4. Dekorátory přístupových objektů
V TypeScriptu existují dva typy přístupových metod: get
a set
. Používají se k řízení přístupu k vlastnostem třídy. Dekorátory přístupových objektů slouží k dekorování těchto metod a deklarují se těsně před deklarací přístupového objektu. Dekorátory accessorů fungují stejně jako dekorátory metod.
Příklad dekorátoru accessorů:
const logKola = (target: any, accessorName: string, descriptor: PropertyDescriptor) => { console.log(`${accessorName} se používá pro získání počtu kol`); console.log(descriptor); } class Vozidlo { private kola: number = 4; constructor() { console.log("Bylo vytvořeno vozidlo") } @logKola get pocetKol(): number { return this.kola; } }
Výstup:
pocetKol se používá pro získání počtu kol { get: [Function: get pocetKol], set: undefined, enumerable: false, configurable: true }
Důležité je, že dekorátory nelze použít na více getterů/setterů se stejným názvem. V příkladu, pokud by byl vytvořen setter s názvem set pocetKol
, nemohl by na něj být použit dekorátor logKola
.
#5. Dekorátory parametrů
Dekorátor parametrů se používá k pozorování deklarace parametru v metodě a deklaruje se před deklarací parametru. Má tři argumenty: konstruktor třídy pro statický člen, nebo prototyp třídy pro instanční člen.
Druhým argumentem je název parametru a třetím je index parametru v seznamu parametrů funkce (první parametr má index 0).
Příklad dekorátoru parametru:
const logCestujiciho = (target: Object, propertyKey: string, parameterIndex: number) => { console.log(`Dekorátor na parametru metody ${propertyKey} s indexem ${parameterIndex}`); } class Vozidlo { private kola: number = 4; constructor() { console.log("Bylo vytvořeno vozidlo") } vyzvedniCestujiciho(location: string, pocetCestujicich: string, @logCestujiciho ridic: string) { console.log(`${pocetCestujicich} vyzvednuto v ${location} řidičem ${ridic}`) } vysadCestujiciho(ridic: string, @logCestujiciho location: string, pocetCestujicich: string) { console.log(`${pocetCestujicich} vysazeno v ${location} řidičem ${ridic}`) } }
Výstup:
Dekorátor na parametru metody vyzvedniCestujiciho s indexem 2 Dekorátor na parametru metody vysadCestujiciho s indexem 1
Závěr
Dekorátory TypeScript výrazně zvyšují čitelnost kódu a umožňují psát modulární a znovupoužitelný kód. Jeden dekorátor lze použít opakovaně na různých místech. Dekorátory přispívají k celkové udržovatelnosti kódu.
Přestože jsou dekorátory stále experimentální funkcí, jsou velmi užitečné a vyplatí se je prozkoumat.
Můžete se také podívat na to, jak převést řetězec na číslo v TypeScriptu.