Atualizado: 21/06/2025

Este conteúdo é original e não foi gerado por inteligência artificial.

Decoradores em Typescript

Decoradores são uma ferramenta de programação declarativa que permitem adicionar metadados a classes e seus membros, modificando seu comportamento sem alterar o código original.

Os decoradores são funções que podem ser aplicadas a classes, métodos, acessores (getters e setters), propriedades e parâmetros.

Decoradores de Classe

Um decorador de classe é aplicado ao construtor da classe e permite modificar ou substituir a definição da classe.

O decorador de classe é uma função que recebe um parâmetro:

function classDecoratorFn(constructor: Function) {}

O parâmetro é o construtor da classe. Por exemplo, vamos definir um decorador simples:

function sealed(constructor: Function) {
  console.log("sealed decorator");
  Object.seal(constructor);
  Object.seal(constructor.prototype);
}

@sealed
class User {
  name: string;
  constructor(name: string) {
    this.name = name;
  }
  print(): void {
    console.log(this.name);
  }
}

O decorador sealed usa a função Object.seal para impedir a extensão do protótipo da classe User.

Para aplicar um decorador, utiliza-se o símbolo @. O decorador é colocado antes da definição da classe. Devido ao uso do decorador, por exemplo, não poderemos adicionar uma nova propriedade à classe User da seguinte forma:

Object.defineProperty(User, "age", {
  value: 17,
});

Além disso, os decoradores podem alterar o resultado do construtor. Nesse caso, a definição da função do decorador muda um pouco, mas ainda recebe o construtor da classe como parâmetro:

function logger<TFunction extends Function>(target: TFunction): TFunction {
  let newConstructor: Function = function (name: string) {
    console.log("Creating new instance");
    this.name = name;
    this.age = 23;
    this.print = function (): void {
      console.log(this.name, this.age);
    };
  };
  return <TFunction>newConstructor;
}

@logger
class User {
  name: string;
  constructor(name: string) {
    this.name = name;
  }
  print(): void {
    console.log(this.name);
  }
}

let tom = new User("Tom");
let bob = new User("Bob");
tom.print();
bob.print();

Neste caso, o decorador logger é tipado com TFunction, que é uma extensão do tipo Function, ou seja, é o tipo de uma função construtora.

No próprio decorador, o construtor passado (target) não é utilizado. Em vez disso, um novo construtor é criado. Suponhamos que o construtor receba um parâmetro chamado name. O valor desse parâmetro é atribuído à propriedade this.name = name;. Além disso, o construtor define uma nova propriedade this.age e um método this.print(), que exibe no console os valores de ambas as propriedades.

Em seguida, o decorador é aplicado à classe User. Esta classe tem um construtor que define a propriedade name. No entanto, como substituímos o construtor, na realidade, ao criar um objeto User, serão definidas tanto a propriedade name quanto a propriedade age. Além disso, o método print será redefinido.

Saída no console do navegador:

Creating new instance
Creating new instance
Tom 23
Bob 23

É importante notar que substituir o construtor resulta na substituição completa de todas as propriedades e métodos da classe.