Como usar decoradores em TypeScript

Decoradores no TypeScript são um recurso poderoso que permite que desenvolvedores adicionem funcionalidade extra a classes, métodos, propriedades e parâmetros. Eles fornecem uma maneira de modificar o comportamento do código existente sem alterar sua estrutura real. Este guia explicará como usar decoradores no TypeScript com exemplos fáceis de seguir.

O que são decoradores?

Decoradores são funções especiais que podem ser aplicadas a classes, métodos, propriedades ou parâmetros. Eles são invocados em tempo de execução e permitem que os desenvolvedores anotem e modifiquem o código de forma declarativa. Para habilitar decoradores em um projeto TypeScript, o sinalizador experimentalDecorators deve ser definido como true no arquivo tsconfig.json.

Habilitando decoradores em TypeScript

Para usar decoradores, o compilador TypeScript deve ser configurado para reconhecê-los. Isso pode ser feito definindo o sinalizador experimentalDecorators como true no arquivo tsconfig.json.

{
  "compilerOptions": {
    "target": "ES6",
    "experimentalDecorators": true
  }
}

Depois que os decoradores estiverem habilitados, eles poderão ser usados ​​em todo o projeto.

Criando um decorador de classe

Um decorador de classe é aplicado a uma declaração de classe e pode ser usado para modificar ou substituir uma definição de classe. Decoradores de classe são declarados logo acima da classe que eles decoram, usando o símbolo @.

function LogClass(target: Function) {
  console.log(`Class ${target.name} is created.`);
}

@LogClass
class Person {
  constructor(public name: string) {}
}

const person = new Person('Alice');

Neste exemplo, o decorador LogClass registra uma mensagem quando a classe Person é criada. O decorador é definido como uma função que recebe um único argumento: o construtor da classe que está sendo decorada.

Decoradores de Método

Os decoradores de método são aplicados a métodos dentro de uma classe. Eles permitem que os desenvolvedores interceptem chamadas de método, modifiquem seu comportamento ou executem operações adicionais antes ou depois que o método seja executado.

function LogMethod(target: Object, propertyKey: string, descriptor: PropertyDescriptor) {
  const originalMethod = descriptor.value;

  descriptor.value = function (...args: any[]) {
    console.log(`Method ${propertyKey} is called with arguments: ${args}`);
    return originalMethod.apply(this, args);
  };

  return descriptor;
}

class Calculator {
  @LogMethod
  add(a: number, b: number): number {
    return a + b;
  }
}

const calc = new Calculator();
calc.add(2, 3);

Aqui, o decorador LogMethod registra o nome do método e seus argumentos sempre que o método add é chamado. Ele encapsula o método original em uma nova função que realiza o registro antes de delegar ao método original.

Decoradores de imóveis

Os decoradores de propriedade são usados ​​para observar ou modificar o comportamento de propriedades de classe. Diferentemente dos decoradores de método, eles não têm acesso ao valor da propriedade em si, mas podem adicionar metadados às propriedades.

function ReadOnly(target: Object, propertyKey: string) {
  Object.defineProperty(target, propertyKey, {
    writable: false
  });
}

class Book {
  @ReadOnly
  title: string = 'TypeScript Guide';
}

const myBook = new Book();
myBook.title = 'New Title'; // This will cause an error in strict mode

Neste exemplo, o decorador ReadOnly é aplicado à propriedade title da classe Book, tornando-a somente leitura ao definir writable como false.

Decoradores de Parâmetros

Decoradores de parâmetros são usados ​​para anotar ou modificar parâmetros de métodos. Eles recebem três argumentos: o objeto alvo, o nome do método e o índice do parâmetro.

function LogParameter(target: Object, propertyKey: string, parameterIndex: number) {
  console.log(`Parameter in position ${parameterIndex} at ${propertyKey} method is decorated.`);
}

class UserService {
  greet(@LogParameter message: string): void {
    console.log(message);
  }
}

const userService = new UserService();
userService.greet('Hello, TypeScript!');

Neste exemplo, o decorador LogParameter é aplicado ao parâmetro message do método greet na classe UserService. O decorador registra informações sobre o parâmetro que está sendo decorado.

Conclusão

Decoradores em TypeScript oferecem uma maneira poderosa de aprimorar a funcionalidade do código sem alterar sua estrutura. Ao alavancar decoradores de classe, método, propriedade e parâmetro, os desenvolvedores podem facilmente adicionar funcionalidade reutilizável em seus projetos. Com os exemplos fornecidos neste guia, é fácil começar a usar decoradores em TypeScript.