Decoradores no TypeScript

Decoradores no TypeScript

Este artigo explica os decoradores no TypeScript.

YouTube Video

Decoradores no TypeScript

Os decoradores no TypeScript são um mecanismo para adicionar funcionalidades ou comportamentos adicionais a classes, métodos, acessores, propriedades ou parâmetros. Os decoradores são uma ferramenta poderosa para melhorar a legibilidade e reutilização do código.

Noções básicas de decoradores

Um decorador é uma função que injeta funcionalidades adicionais em uma classe ou em membros da classe. Os decoradores foram introduzidos no TypeScript 1.5 e também foram propostos para o padrão ECMAScript.

1{
2  "compilerOptions": {
3    "experimentalDecorators": true
4  }
5}
  • Para usar os decoradores, é necessário habilitar a opção experimentalDecorators no arquivo tsconfig.json.

Tipos de decoradores

No TypeScript, você pode usar os cinco decoradores a seguir.

  • Decorador de Classe Um decorador aplicado a uma classe.
  • Decorador de Método Um decorador aplicado a um método de uma classe.
  • Decorador de Acessor Um decorador aplicado a um getter ou setter de uma propriedade de classe.
  • Decorador de Propriedade Um decorador aplicado a uma propriedade de uma classe.
  • Decorador de Parâmetro Um decorador aplicado a um parâmetro de um método.

Decorador de Classe

Os decoradores de classe são decoradores aplicados a classes. Os decoradores de classe são escritos logo acima da definição da classe e podem acessar o construtor da classe. Eles são usados principalmente para alterar o comportamento da classe ou adicionar metadados.

 1function Logger(constructor: Function) {
 2    console.log(`Class ${constructor.name} is being constructed`);
 3}
 4
 5@Logger
 6class Person {
 7    constructor(public name: string) {}
 8}
 9
10const person = new Person('John');
11// Output: Class Person is being constructed

Neste exemplo, o decorador Logger é aplicado à classe e uma mensagem é exibida no console quando a classe é inicializada.

Decorador de Método

Os decoradores de método são aplicados aos métodos de classe e podem alterar as chamadas e o comportamento dos métodos. Um decorador de método recebe três argumentos.

  1. O protótipo da classe
  2. O nome do método
  3. O descritor de propriedade do método
 1function LogExecutionTime(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
 2    const originalMethod = descriptor.value;
 3
 4    descriptor.value = function (...args: any[]) {
 5        console.time(propertyKey);
 6        const result = originalMethod.apply(this, args);
 7        console.timeEnd(propertyKey);
 8        return result;
 9    };
10}
11
12class MathOperations {
13  @LogExecutionTime
14  add(a: number, b: number): number {
15    return a + b;
16  }
17}
18
19const math = new MathOperations();
20math.add(2, 3);
21// Output: add: 0.000ms (execution time is displayed)

Neste exemplo, o decorador LogExecutionTime é aplicado ao método, e o tempo de execução do método é registrado.

Decorador de Acessor

Os decoradores de acessor são aplicados ao getter ou setter das propriedades da classe. Eles são úteis para adicionar comportamento ao alterar os valores de propriedades.

 1function LogAccess(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
 2    const originalGet = descriptor.get;
 3    const originalSet = descriptor.set;
 4
 5    if (originalGet) {
 6        descriptor.get = function () {
 7            console.log(`Getter called for ${propertyKey}`);
 8            return originalGet.call(this);
 9        };
10    }
11
12    if (originalSet) {
13        descriptor.set = function (value: any) {
14            console.log(`Setter called for ${propertyKey} with value: ${value}`);
15            originalSet.call(this, value);
16        };
17    }
18}
19
20class Car {
21    private _speed: number = 0;
22
23    @LogAccess
24    get speed() {
25        return this._speed;
26    }
27
28    set speed(value: number) {
29        this._speed = value;
30    }
31}
32
33const car = new Car();
34car.speed = 120;               // Setter called for speed with value: 120
35console.log(car.speed);       // Getter called for speed → 120

Neste exemplo, um decorador de acessor é usado para registrar (logar) a saída quando o getter e o setter são chamados.

Decorador de Propriedade

Os decoradores de propriedade são aplicados às propriedades da classe, mas não podem alterar diretamente o valor ou comportamento da propriedade. Eles são usados para obter metadados de propriedades.

 1function Readonly(target: any, propertyKey: string) {
 2    Object.defineProperty(target, propertyKey, {
 3        writable: false
 4    });
 5}
 6
 7class Book {
 8    @Readonly
 9    title: string = "TypeScript Guide";
10}
11
12const book = new Book();
13book.title = "New Title"; // Error: Cannot assign to read only property 'title'

Neste exemplo, o decorador Readonly é aplicado à propriedade title, e a propriedade é tornada somente leitura.

Decorador de Parâmetro

Os decoradores de parâmetro são aplicados aos parâmetros de um método. Eles geralmente são usados para armazenar metadados ou validar parâmetros. Os decoradores recebem três argumentos.

  1. O protótipo da classe
  2. O nome do método
  3. Índice do Parâmetro
 1function LogParameter(target: any, propertyKey: string, parameterIndex: number) {
 2    console.log(`Parameter at index ${parameterIndex} in method ${propertyKey} was decorated.`);
 3}
 4
 5class User {
 6    greet(@LogParameter message: string) {
 7        console.log(message);
 8    }
 9}
10
11const user = new User();
12user.greet('Hello!');
13// Output: Parameter at index 0 in method greet was decorated.

Neste exemplo, o decorador LogParameter é aplicado ao primeiro parâmetro do método greet, e quando o método é chamado, registra que o parâmetro está decorado.

Exemplos Práticos de Decoradores

Os decoradores são amplamente usados em frameworks como Angular, especialmente para injeção de dependência e definição de metadados. Por exemplo, use o decorador @Component para definir componentes Angular, como mostrado abaixo.

1@Component({
2    selector: 'app-root',
3    template: '<h1>Hello World</h1>',
4})
5export class AppComponent {}

Assim, os decoradores são frequentemente usados como partes centrais de frameworks e bibliotecas, ajudando a manter o código conciso e claro.

Resumo dos Decoradores

Os decoradores do TypeScript são ferramentas poderosas que adicionam funcionalidade de forma flexível a classes, métodos e propriedades. O uso de decoradores personalizados melhora a manutenibilidade e a reutilização do código, permitindo maior abstração. Os decoradores desempenham um papel importante em frameworks como Angular e NestJS, e entendê-los ajuda a compreender profundamente como esses frameworks funcionam.

Você pode acompanhar o artigo acima usando o Visual Studio Code em nosso canal do YouTube. Por favor, confira também o canal do YouTube.

YouTube Video