Teraz pisz czystszy i mądrzejszy kod

TypeScript to język programowania o silnym typowaniu, który opiera się na JavaScript, zapewniając lepsze narzędzia na dużą skalę. TypeScript został opracowany, aby pomóc rozwiązać niektóre problemy pojawiające się podczas pisania kodu przy użyciu JavaScript. TypeScript pokonuje pułapki JavaScriptu poprzez użycie typów.

Każda wartość w kodzie źródłowym maszynopisu ma typ. TypeScript sprawdza, czy każda wartość jest zgodna z regułami związanymi z jej typem. TypeScript sprawdza błędy w kodzie źródłowym bez konieczności uruchamiania programu.

Nazywa się to statycznym sprawdzaniem typu i polega na sprawdzaniu błędów w rozwoju na podstawie typu wartości używanych w programie.

Oprócz pomocy w pisaniu bardziej przejrzystego i czytelnego kodu oraz zapewnianiu statycznego sprawdzania typu, TypeScript oferuje dodatkowe funkcje poprawiające czytelność kodu, możliwość ponownego użycia i łatwość konserwacji. Jedną z takich funkcji są dekoratory TypeScript.

Dekoratory TypeScriptu

Dekoratory w TypeScript to funkcja, która pozwala zmieniać lub ulepszać zachowanie kodu w czasie wykonywania lub dodawać metadane do kodu. Dekoratory umożliwiają metaprogramowanie w TypeScript. Metaprogramowanie to technika programowania, w której programy mogą traktować inne programy jak swoje dane i w ten sposób modyfikować swoje zachowanie.

Zasadniczo dekoratory to funkcje, które zostaną wywołane w celu wykonania pewnej logiki w czasie wykonywania, gdy uzyskany zostanie dostęp lub modyfikacja dekorowanych elementów.

W ten sposób dekorowanym elementom można dodać dodatkową funkcjonalność. Dekoratory TypeScriptu można dołączać do deklaracji klas, metod, właściwości, akcesorów (getterów i setterów) oraz parametrów metod.

W TypeScript dekoratory są poprzedzone symbolem @ i przyjmują formę @wyrażenia z wyrażeniem wyznaczającym funkcję, która zostanie wywołana w czasie wykonywania. Ogólna składnia używania dekoratorów w TypeScript jest pokazana poniżej:

@decoratorName
itemToDecorate

Przykład prostego dekoratora klas pokazano poniżej:

function logClass(target: Function) {
  console.log("The Log Class Decorator has been called")
  console.log("Class:", target);
}

@logClass // @logClass is a decorator
class MyClass {
  constructor() {
    console.log("An instance of MyClass has been created");
  }
}

const myInstance = new MyClass();

Wynik wykonania powyższego kodu pokazano poniżej:

Wyjście:

The Log Class Decorator has been called
Class: [class MyClass]
An instance of MyClass has been created

Funkcja logClass() przyjmuje pojedynczy argument zwany celem typu Function. Argument target jest typu Function, ponieważ otrzyma konstruktor klasy, którą dekorujemy.

Aby użyć logClass() jako dekoratora do dekoracji klasy o nazwie MyClass, umieszczamy @logclass tuż przed deklaracją MyClass. Dekorator musi mieć taką samą nazwę jak funkcja, której chcesz użyć do dekoracji elementu.

Kiedy tworzona jest instancja MyClass, oprócz konstruktora klasy wykonywane jest zachowanie dekoratora, jak pokazano na wyjściu.

Dekoratory są obecnie dostępne w TypeScript jako funkcja eksperymentalna. Dlatego, aby móc używać dekoratorów w języku TypeScript, należy włączyć eksperymentalneDekoratory w opcji kompilatora w pliku tsconfig.json.

Aby to zrobić, wygeneruj plik tsconfig.json w folderze projektu TypeScript, wykonując następujące polecenie w terminalu otwartym w katalogu projektu:

tsc --init

Gdy już będziesz mieć plik tsconfig.json, otwórz go i usuń komentarz z eksperymentalnychDekoratorów, jak pokazano poniżej:

Dodatkowo ustaw docelową wersję JavaScript na co najmniej ES2015.

Znaczenie dekoratorów TypeScriptu

Dobry kod można łatwo określić na podstawie tego, jak czytelny, możliwy do ponownego użycia i łatwy w utrzymaniu jest kod. Czytelny kod to kod, który jest łatwy do zrozumienia i interpretacji oraz jasno przekazuje intencje programisty każdemu, kto czyta kod.

Z drugiej strony kod wielokrotnego użytku to kod, który umożliwia zmianę przeznaczenia, adaptację i wykorzystanie określonych komponentów, takich jak funkcje i klasy, i wykorzystanie ich w innych częściach aplikacji lub zupełnie nowej aplikacji bez znaczących modyfikacji.

Kod utrzymywalny to kod, który można łatwo modyfikować, aktualizować i naprawiać w trakcie jego istnienia.

Dekoratory TypeScript umożliwiają osiągnięcie czytelności kodu, możliwości ponownego użycia i łatwości konserwacji. Po pierwsze, dekoratory TypeScriptu pozwalają ulepszyć zachowanie kodu przy użyciu deklaratywnej składni, która jest łatwiejsza do odczytania. Możesz enkapsulować logikę w dekoratorach i wywoływać je, dekorując różne elementy kodu tam, gdzie potrzebujesz logiki.

Dzięki temu Twój kod będzie łatwy do odczytania i zrozumienia, co się dzieje. Dekoratory jasno komunikują intencje dewelopera.

Dekoratory nie są elementami jednorazowego użytku; z natury nadają się do ponownego użycia. Możesz stworzyć dekorator raz i używać go wielokrotnie w wielu obszarach.

Dlatego możesz definiować dekoratory, importować je i używać ich w dowolnym miejscu w bazie kodu, w którym chcesz zmodyfikować zachowanie swojego kodu. Jest to korzystne, ponieważ pozwala uniknąć powielania logiki w bazie kodu, zwiększając w ten sposób możliwość ponownego użycia kodu.

Dekoratory zapewniają także dużą elastyczność i modułowość kodu, umożliwiając rozdzielenie różnych funkcjonalności na niezależne komponenty. To, w połączeniu z faktem, że pozwalają one na pisanie czytelnego i wielokrotnego użytku kodu, oznacza, że ​​dekoratory TypeScript umożliwią stworzenie kodu, który będzie łatwy w utrzymaniu.

Rodzaje dekoratorów TypeScriptu

Jak wspomniano wcześniej, dekoratory TypeScriptu można dołączać do klas, właściwości klas, metod klas, akcesoriów klas i parametrów metod klas. Z elementów, które możemy ozdobić, otrzymujemy różne typy dekoratorów TypeScript. Do tych dekoratorów należą:

#1. Dekorator klas

Dekorator klas to dekorator używany do obserwowania, modyfikowania lub zastępowania definicji klasy. Jest deklarowany tuż przed klasą, którą dekoruje. Dekorator klasy jest stosowany do konstruktora klasy, którą dekoruje. W czasie wykonywania zostanie wywołany dekorator klasy, którego jedynym argumentem będzie konstruktor klasy, którą dekoruje.

Poniżej pokazano dekorator klas, który zapobiega rozszerzaniu klasy:

function frozen(target: Function) {
  Object.freeze(target);
  Object.freeze(target.prototype)
}

@frozen
class Vehicle {
  wheels: number = 4;
  constructor() {
    console.log("A vehicle has been created")
  }
}

class Car extends Vehicle {
  constructor() {
    super();
    console.log("A car has been created");
  }
}

console.log(Object.isFrozen(Vehicle));

Aby zapobiec rozszerzaniu klasy, używamy funkcji Object.freeze() i przekazujemy klasę, którą chcemy zamrozić. Dekorator służy do dodawania tej funkcjonalności do klasy. Możemy sprawdzić, czy klasa Vehicle jest zamrożona w czasie wykonywania, przekazując klasę do isFrozen(). Wynik kodu pokazano poniżej:

true

#2. Dekorator Nieruchomości

Dekorator właściwości służy do dekorowania właściwości klasy i jest deklarowany tuż przed dekoracją właściwości. Dekoratorów właściwości można używać do zmiany lub obserwowania definicji właściwości.

W czasie wykonywania zostanie wywołany dekorator, który przyjmuje dwa argumenty. Po pierwsze, albo funkcja konstruktora klasy, jeśli element jest statyczny, albo prototyp klasy, jeśli jest to element instancji. Drugim argumentem jest nazwa członka, czyli nieruchomości, którą dekorujesz.

W TypeScript elementy statyczne mają przed sobą słowo kluczowe static. Dostęp do elementów statycznych można uzyskać bez tworzenia instancji klasy. Elementy instancji nie mają przed sobą słowa kluczowego static i można uzyskać do nich dostęp dopiero po utworzeniu instancji klasy.

Przykład dekoratora nieruchomości pokazano poniżej:

function wheelsDecorator(target: any, propertyName: string) {
  console.log(propertyName.toUpperCase())
}

class Vehicle {
  @wheelsDecorator
  wheels: number = 4;
  constructor() {
    console.log("A vehicle has been created")
  }
}

Wynik uruchomienia kodu pokazano poniżej:

WHEELS

#3. Dekorator metod

Dekorator metody, zadeklarowany tuż przed deklaracją metody, jest dekoratorem używanym do obserwowania, modyfikowania lub zastępowania definicji metody. Przyjmuje trzy argumenty: funkcję konstruktora klasy, jeśli element jest statyczny, lub właściwość klasy, jeśli jest elementem instancji.

Drugim argumentem jest nazwa elementu członkowskiego i na koniec deskryptor właściwości tego elementu. Deskryptor właściwości to obiekt powiązany z właściwościami obiektu i dostarcza informacji o atrybutach i zachowaniu właściwości.

Dekoratory metod przydają się, gdy chcesz wykonać jakąś akcję przed wywołaniem metody lub po jej wywołaniu. Możemy za ich pomocą także rejestrować informacje o wywoływanej metodzie. Może to być przydatne, jeśli chcesz poinformować użytkownika, że ​​dana metoda jest przestarzała; oznacza to, że jest nadal dostępny do użytku, ale nie zaleca się jego używania, ponieważ może zostać później usunięty.

Przykład dekoratora metod pokazano poniżej:

const logDeprecated =(target: any, methodName: string, descriptor: PropertyDescriptor) => {
  console.log(`${methodName} has been deprecated`)
  console.log(descriptor);
}

class Vehicle {
  wheels: number = 4;
  constructor() {
    console.log("A vehicle has been created")
  }
  @logDeprecated
  reFuel(): void {
    console.log("Your vehicle is being refuelled");
  }
}

Wyjście:

reFuel has been deprecated
{
  value: [Function: reFuel],
  writable: true,
  enumerable: false,
  configurable: true
}

#4. Dekoratorzy akcesoriów

W TypeScript istnieją dwa typy metod dostępu: get i set. Metody akcesorów służą do kontrolowania dostępu do właściwości klasy. Dekoratory akcesorów służą do dekorowania tych dwóch metod akcesorów i są deklarowane tuż przed deklaracją akcesora. Ponieważ akcesory są nadal metodami, dekoratory akcesorów działają tak samo jak dekoratory metod.

Przykład dekoratorów akcesoriów pokazano poniżej:

const logWheels =(target: any, accessorName: string, descriptor: PropertyDescriptor) => {
  console.log(`${accessorName} used to get the number of wheels`)
  console.log(descriptor);
}

class Vehicle {
  private wheels: number = 4;
  constructor() {
    console.log("A vehicle has been created")
  }
  @logWheels
  get numWheels(): number {
    return this.wheels;
  }
}

Wyjście:

numWheels used to get the number of wheels
{
  get: [Function: get numWheels],
  set: undefined,
  enumerable: false,
  configurable: true
}

W przypadku dekoratorów akcesorów należy pamiętać, że dekoratorów nie można stosować do wielu akcesorów get/set o tej samej nazwie. Na przykład w powyższym przykładzie kodu, jeśli utworzysz seter o nazwie set numWheels, nie możesz użyć na nim dekoratora logWheels.

#5. Dekoratory parametrów

Dekorator parametrów służy do obserwacji, czy parametr został zadeklarowany w metodzie i jest zadeklarowany przed deklaracją parametru. Dekoratory parametrów przyjmują trzy argumenty, po pierwsze, funkcję konstruktora klasy dla elementu statycznego lub prototyp klasy dla elementu instancji.

Drugim argumentem jest nazwa elementu, czyli nazwa parametru. Trzeci argument jest indeksem porządkowym parametru na liście parametrów funkcji. Oznacza to, że na liście parametrów jaką pozycję zajmuje parametr, przy czym pierwszy parametr ma indeks 0?

Przykład dekoratora parametrów pokazano poniżej:

const passengerLog = (target: Object, propertyKey: string, parameterIndex: number) => {
  console.log(`Decorator on ${propertyKey}'s paremeter index ${parameterIndex}`);
}

class Vehicle {
  private wheels: number = 4;
  constructor() {
    console.log("A vehicle has been created")
  }
  pickPassenger( location: string, numPassengers: string, @passengerLog driver: string) {
    console.log(`${numPassengers} picked at ${location} by ${driver}`)
  }
  dropPassenger(driver: string, @passengerLog location: string, numPassengers: string) {
    console.log(`${numPassengers} dropped at ${location} by ${driver}`)
  }
}

Wyjście:

Decorator on pickPassenger's paremeter index 2
Decorator on dropPassenger's paremeter index 1

Wniosek

Dekoratory TypeScript wnoszą ogromny wkład w poprawę czytelności kodu i pomagają w pisaniu modułowego kodu wielokrotnego użytku, ponieważ możesz zadeklarować dekoratory raz i używać ich wiele razy. Dodatkowo dekoratory przyczyniają się do ogólnej łatwości konserwacji kodu.

Dekoratory są nadal funkcją eksperymentalną, ale są bardzo przydatne i zdecydowanie powinieneś rozważyć zapoznanie się z nimi.

Możesz także przeczytać, jak przekonwertować ciąg znaków na liczbę w TypeScript.