TypeScript är ett kraftfullt, typat programmeringsspråk som bygger vidare på JavaScript och erbjuder förbättrade verktyg för större projekt. Det utvecklades för att hantera de utmaningar som uppstår vid programmering med JavaScript. Genom att införa typer, eliminerar TypeScript många av de fallgropar som finns i JavaScript.
I TypeScript-källkod tilldelas varje värde en specifik typ. TypeScript kontrollerar att varje värde överensstämmer med reglerna för sin typ. Det här innebär att TypeScript identifierar fel i koden utan att programmet behöver köras.
Denna metod kallas statisk typkontroll, vilket betyder att fel detekteras under utvecklingsfasen baserat på de typer av värden som används i koden.
Utöver att bidra till tydligare och mer lättläst kod samt tillhandahålla statisk typkontroll, erbjuder TypeScript ytterligare funktioner som förbättrar kodens läsbarhet, återanvändbarhet och underhåll. Ett exempel på detta är TypeScript-dekoratörer.
TypeScript-dekoratörer
Dekoratörer i TypeScript är funktioner som modifierar eller förbättrar kodens beteende vid körning eller lägger till metadata. De möjliggör metaprogrammering, en teknik där program kan manipulera andra program som data och därigenom ändra sitt eget beteende.
Dekoratörer är i grunden funktioner som anropas för att utföra logik när dekorerade element nås eller modifieras. Detta ger möjligheten att utöka funktionaliteten för dessa element. TypeScript-dekoratörer kan knytas till klassdeklarationer, metoder, egenskaper, accessorer (getters och setters) och metodparametrar.
I TypeScript inleds dekoratörer med symbolen @ och har formen @uttryck, där uttrycket resulterar i en funktion som anropas vid körning. Den allmänna syntaxen för att använda dekoratörer ser ut som följer:
@decoratorNamn elementAttDekorera
Här är ett exempel på en enkel klassdekoratör:
function loggaKlass(target: Function) { console.log("Klassdekoratören har anropats") console.log("Klass:", target); } @loggaKlass // @loggaKlass är en dekoratör class MinKlass { constructor() { console.log("En instans av MinKlass har skapats"); } } const minInstans = new MinKlass();
Resultatet av att köra ovanstående kod är:
Output:
Klassdekoratören har anropats Klass: [class MinKlass] En instans av MinKlass har skapats
Funktionen `loggaKlass()` tar ett argument kallat `target` av typen `Function`. Argumentet är av typen `Function` eftersom det mottar konstruktorn för den klass som dekoreras. För att använda `loggaKlass()` som dekoratör för klassen `MinKlass` placeras `@loggaKlass` direkt före klassdeklarationen. Dekoratorns namn måste matcha namnet på funktionen som ska användas för dekoration.
När en instans av `MinKlass` skapas, utförs dekoratörens logik utöver klasskonstruktorn, som visas i utmatningen.
Dekoratörer är för närvarande en experimentell funktion i Typescript. För att aktivera dem måste `experimentalDecorators` aktiveras i kompilatorinställningarna i filen `tsconfig.json`.
Skapa filen `tsconfig.json` i din TypeScript-projektmapp genom att köra följande kommando i terminalen:
tsc --init
Öppna sedan filen `tsconfig.json` och kommentera bort `experimentalDecorators` enligt nedan:
Se även till att JavaScript-målversionen är satt till minst ES2015.
Vikten av TypeScript-dekoratörer
Välskriven kod kännetecknas av läsbarhet, återanvändbarhet och underhållsvänlighet. Läsbar kod är kod som är lätt att förstå och tolka, där utvecklarens intention tydligt kommuniceras. Återanvändbar kod möjliggör att komponenter som funktioner och klasser kan återanvändas, anpassas och integreras i olika delar av en applikation, eller i helt nya applikationer, utan omfattande ändringar.
Underhållsvänlig kod är kod som enkelt kan modifieras, uppdateras och korrigeras under sin livstid.
TypeScript-dekoratörer bidrar till att uppnå läsbar, återanvändbar och underhållsvänlig kod. Genom att använda en deklarativ syntax som är lättare att läsa, kan man förbättra kodens beteende. Logik kan kapslas in i dekoratörer och återanvändas genom att dekorera olika element i koden. Det gör koden mer överskådlig och tydlig i vad den gör, vilket tydligt kommunicerar utvecklarens intention.
Dekoratörer är inte engångsföreteelser; de är återanvändbara. En dekoratör kan skapas en gång och sedan användas flera gånger på olika ställen. Detta eliminerar duplicering av logik och ökar kodens återanvändbarhet.
Dekoratörer ger också flexibilitet och modularitet, vilket möjliggör att separera olika funktioner i oberoende komponenter. Tillsammans med läsbarheten och återanvändbarheten, bidrar det till att TypeScript-dekoratörer leder till kod som är enkel att underhålla.
Typer av TypeScript-dekoratörer
TypeScript-dekoratörer kan appliceras på klasser, klassegenskaper, klassmetoder, klassaccessorer och klassmetodparametrar. Från dessa element kan vi definiera olika typer av TypeScript-dekoratörer.
#1. Klassdekoratör
En klassdekoratör används för att observera, modifiera eller ersätta en klassdefinition. Den deklareras omedelbart före klassen som ska dekoreras. En klassdekoratör appliceras på konstruktorn för klassen. Vid körning anropas klassdekoratören med klassens konstruktor som enda argument.
Här följer ett exempel på en klassdekoratör som förhindrar att en klass utökas:
function frys(target: Function) { Object.freeze(target); Object.freeze(target.prototype) } @frys class Fordon { hjul: number = 4; constructor() { console.log("Ett fordon har skapats") } } class Bil extends Fordon { constructor() { super(); console.log("En bil har skapats"); } } console.log(Object.isFrozen(Fordon));
Funktionen `Object.freeze()` används för att frysa en klass och förhindra utökning. En dekoratör applicerar den här funktionen på en klass. Genom att skicka klassen till `isFrozen()` kan man kontrollera om fordonsklassen är fryst vid körning. Utmatningen av koden är:
true
#2. Egenskapsdekoratör
En egenskapsdekoratör används för att dekorera en klass-egenskap. Den deklareras strax före egenskapens deklaration. Egenskapsdekoratörer kan användas för att ändra eller observera definitionen av en egenskap. Vid körning anropas dekoratören med två argument. Det första argumentet är konstruktorfunktionen för klassen om medlemmen är statisk eller klassens prototyp om det är en instansmedlem. Det andra argumentet är namnet på egenskapen som dekoreras.
I TypeScript markeras statiska medlemmar med nyckelordet `static`. Statiska medlemmar kan nås utan att instansiera klassen. Instansmedlemmar saknar nyckelordet `static` och kan endast nås efter att en instans av klassen har skapats.
Här följer ett exempel på en egenskapsdekoratör:
function hjulDekorator(target: any, propertyName: string) { console.log(propertyName.toUpperCase()) } class Fordon { @hjulDekorator hjul: number = 4; constructor() { console.log("Ett fordon har skapats") } }
Resultatet av att köra koden:
HJUL
#3. Metoddekoratör
En metoddekoratör deklareras strax före en metoddeklaration och används för att observera, modifiera eller ersätta en metoddefinition. Den tar emot tre argument: klassens konstruktorfunktion om metoden är statisk eller klassens prototyp om det är en instansmedlem. Det andra argumentet är metodens namn, och det tredje är en egenskapbeskrivning för metoden. En egenskapbeskrivning är ett objekt som beskriver attribut och beteenden för en egenskap.
Metoddekoratörer är användbara när man vill utföra åtgärder före eller efter att en metod anropas, eller för att logga information om den anropade metoden. Det kan även användas för att informera användare om att en metod är föråldrad, dvs att den fortfarande är tillgänglig men inte rekommenderas för användning och kan komma att tas bort i framtiden.
Här är ett exempel på en metoddekoratör:
const loggaForaldrad =(target: any, methodName: string, descriptor: PropertyDescriptor) => { console.log(`${methodName} har blivit föråldrad`) console.log(descriptor); } class Fordon { hjul: number = 4; constructor() { console.log("Ett fordon har skapats") } @loggaForaldrad tankafull(): void { console.log("Ditt fordon tankas"); } }
Output:
tankafull har blivit föråldrad { value: [Function: tankafull], writable: true, enumerable: false, configurable: true }
#4. Accessordekoratörer
I TypeScript finns det två typer av accessormetoder: get och set. Accessormetoder används för att kontrollera åtkomsten till klassers egenskaper. Accessordekoratörer används för att dekorera dessa metoder och deklareras strax före accessordeklarationen. Eftersom accessorer är metoder fungerar accessordekoratörer på samma sätt som metoddekoratörer.
Här är ett exempel på en accessordekoratör:
const loggaHjul =(target: any, accessorName: string, descriptor: PropertyDescriptor) => { console.log(`${accessorName} används för att hämta antalet hjul`) console.log(descriptor); } class Fordon { private hjul: number = 4; constructor() { console.log("Ett fordon har skapats") } @loggaHjul get antalHjul(): number { return this.hjul; } }
Output:
antalHjul används för att hämta antalet hjul { get: [Function: get antalHjul], set: undefined, enumerable: false, configurable: true }
Med accessordekoratörer är det viktigt att notera att de inte kan användas på flera get/set-accessorer med samma namn. Om du till exempel skapar en setter med namnet set antalHjul i exemplet ovan, kan du inte använda dekoratören loggaHjul på den.
#5. Parameterdekoratörer
En parameterdekoratör används för att observera att en parameter har deklarerats i en metod, och den deklareras före parameterdeklarationen. Parameterdekoratörer tar emot tre argument: klassens konstruktorfunktion för en statisk medlem eller klassens prototyp för en instansmedlem. Det andra argumentet är namnet på metoden och det tredje argumentet är ordningsindexet för parametern i funktionens parameterlista, där det första indexet börjar på 0.
Här följer ett exempel på en parameterdekoratör:
const passagerarLogg = (target: Object, propertyKey: string, parameterIndex: number) => { console.log(`Dekorator på ${propertyKey}'s parameter index ${parameterIndex}`); } class Fordon { private hjul: number = 4; constructor() { console.log("Ett fordon har skapats") } hamtaPassagerare( plats: string, antalPassagerare: string, @passagerarLogg forare: string) { console.log(`${antalPassagerare} hamtades vid ${plats} av ${forare}`) } slappAvPassagerare(forare: string, @passagerarLogg plats: string, antalPassagerare: string) { console.log(`${antalPassagerare} avlastade vid ${plats} av ${forare}`) } }
Output:
Dekorator på hamtaPassagerare's parameter index 2 Dekorator på slappAvPassagerare's parameter index 1
Slutsats
TypeScript-dekoratörer är ett kraftfullt verktyg för att förbättra kodens läsbarhet och skapa modulär, återanvändbar kod. Genom att deklarera dekoratörer en gång och sedan använda dem flera gånger kan man minska repetition. Dekoratörer bidrar också till den totala underhållsvänligheten av koden. Trots att de fortfarande är en experimentell funktion, är dekoratörer mycket användbara och värda att utforska.
Du kan också läsa om hur man konverterar en sträng till ett tal i TypeScript.