# Como usar TypeScript decorators

**TypeScript decorators** são uma maneira prática e simples de adicionar funcionalidades extras a objetos sem modificar o código original. Eles podem ser aplicados a classes, métodos, propriedades e parâmetros, aprimorando anotações e metadados.

## O que são TypeScript decorators e por que usá-los?

O princípio adotado por TypeScript decorators não é novo. Outras linguagens de programação oferecem recursos similares, como atributos em C#, Decorators em Python e anotações em Java. Decorators **expandem a funcionalidade de um objeto** sem modificar o código original. O [TypeScript](https://www.ionos.com/pt-br/digitalguide/sites-de-internet/desenvolvimento-web/typescript/ "TypeScript") já tem utilizado essa abordagem há algum tempo. Embora a maioria dos navegadores ainda não suporte TypeScript decorators, vale a pena explorar essa abordagem e suas possibilidades

TypeScript decorators são usados para **adicionar anotações e metadados adicionais** a [classes TypeScript](https://www.ionos.com/pt-br/digitalguide/sites-de-internet/desenvolvimento-web/typescript-classes/ "Classes TypeScript") e seus elementos. Eles são capazes de modificar não apenas classes, mas também métodos, propriedades, métodos de acesso e parâmetros. Esses últimos podem ser validados e seus valores recuperados, seu grande diferencial em relação ao equivalente JavaScript.

## Sintaxe e funcionamento de TypeScript decorators

Ao adicionar decorators a um objeto TypeScript, você está tecnicamente invocando uma [função TypeScript](https://www.ionos.com/pt-br/digitalguide/sites-de-internet/desenvolvimento-web/typescript-functions/ "Funções TypeScript") que **pode ser executada sem alterar o código original**. Isso aumenta a funcionalidade do código por mantê-lo limpo. A sintaxe básica de um TypeScript decorator é a seguinte:

```typescript
@nomeDoDecorator
```

Essa função pode ser criada com dois ou três parâmetros. A sintaxe para a função com três parâmetros é:

```typescript
function decoratorFunction(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
    console.log(`Decorating ${propertyKey} of class ${target.constructor.name}`);
}
 
class MyClass {
    @decoratorFunction
    myMethod() {}
}
```

Estes são os elementos do TypeScript decorators:

- `target`: Refere-se ao objeto ao qual o decorator foi atribuído.
- `propertyKey`: É a string que contém o nome da classe à qual o decorator foi atribuído, seja um método ou atributo.
- `descriptor`: Contém informações sobre o objeto ao qual o decorator é aplicado. Entre os atributos estão `value`, `writable`, `enumerable` ou `configurable`.

Aqui está a sintaxe de um TypeScript decorator com dois parâmetros:

```typescript
function decoratorFunction(target: any) {
    console.log(`Decorating ${target.name}`);
}
 
@decoratorFunction
class MyClass {}
```

Nesse caso, o decorator foi aplicado a uma classe.

## Tipos de TypeScript decorators

Existem diferentes tipos de TypeScript decorators, cada um com suas características próprias:

- Class decorators
- Method decorators
- Property decorators
- Accessor decorators
- Parameter decorators

## Class decorators: TypeScript decorators para classes

Para modificar as **características de uma classe**, como seu construtor, métodos ou propriedades, TypeScript decorators são uma ótima opção. O primeiro parâmetro recebido é o construtor, assim que você “decora” a classe com uma função. Observe abaixo um exemplo de código. Ele contém uma classe com propriedades privadas e públicas:

```typescript
class Cliente {
  private static userType: string = "Genérico";
  private _email: string;
 
  public nome: string;
  public endereco: string = "";
  public cidade: string = "";
  public pais: string = "";
 
  constructor(nome: string, email: string) {
    this.nome = nome;
    this._email = email;
  }
 
  static get tipoUsuario() { 
return Cliente.userType; 
}
 
  get email() {
    return this._email;
  }
 
  set email(novoEmail: string) {
    this._email = novoEmail;
  }
 
  enderecoCompleto(): string {
    return `${this.endereco}\n${this.cidade}\n${this.pais}`;
  }
}
 
const c = new Cliente("ExemploCliente", "nome@exemplo.com");
c.endereco = "Rua Exemplo 2";
c.cidade = "São Paulo";
```

No próximo passo, usamos um TypeScript decorator para adicionar mais funcionalidades sem modificar o código original. Adicionamos o decorator `@frozen` à classe “Cliente”, impedindo alterações nos objetos após sua criação. Em algumas propriedades, usamos `@required` para indicar obrigatoriedade e `@enumerable` para listagens. Também usamos `@deprecated` para sinalizar entradas obsoletas. Primeiramente, definimos os decorators:

```typescript
function frozen(constructor: Function) {
    Object.freeze(constructor);
    Object.freeze(constructor.prototype);
}
 
function required(target: any, propertyKey: string) {
    // Lógica para Required Decorator
}
 
function enumerable(value: boolean) {
    return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
        descriptor.enumerable = value;
    };
}
 
function deprecated(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
    console.warn(`O método ${propertyKey} está obsoleto.`);
}
```

Após aplicarmos TypeScript decorators, o código final fica assim:

```typescript
@frozen
class Cliente {
  private static userType: string = "Genérico";
 
  @required
  private _email: string;
 
  @required
  public nome: string;
 
  public endereco: string = "";
  public cidade: string = "";
  public pais: string = "";
 
  constructor(nome: string, email: string) {
    this.nome = nome;
    this._email = email;
  }
 
  @enumerable(false)
  get userType() {
    return Cliente.userType;
  }
 
  get email() {
    return this._email;
  }
 
  set email(novoEmail: string) {
    this._email = novoEmail;
  }
 
  @deprecated
  enderecoCompleto(): string {
    return `${this.endereco}\n${this.cidade}\n${this.pais}`;
  }
}
 
const c = new Cliente("ExemploCliente", "nome@exemplo.com");
c.endereco = "Rua Exemplo 2";
c.cidade = "São Paulo";
```

## Method decorators: TypeScript decorators para métodos

Você pode aplicar TypeScript decorators a métodos, exceto em arquivos de declaração, sobrecargas ou na palavra-chave `declare`. No exemplo a seguir, usamos `@enumerable` como decorator para o método `getNome` na classe “Pessoa”:

```typescript
const enumerable = (value: boolean) => {
  return (target: any, propertyKey: string, propertyDescriptor: PropertyDescriptor) => {
    propertyDescriptor.enumerable = value;
  }
}
 
class Pessoa {
  primeiroNome: string = "Julia";
  ultimoNome: string = "Silva";
 
  @enumerable(true)
  getNome() {
    return `${this.primeiroNome} ${this.ultimoNome}`;
  }
}
```

## Property decorators: TypeScript decorators para propriedades

TypeScript decorators aplicados a propriedades de uma classe têm dois parâmetros: a função do construtor da classe e o nome da propriedade. No exemplo abaixo, o decorator é usado para exibir o nome de uma propriedade (neste caso, o nome do cliente):

```typescript
const printPropertyName = (target: any, propertyName: string) => {
  console.log(propertyName);
};
 
class Cliente {
  @printPropertyName
  nome: string = "Julia";
}
```

## Accessor decorators: TypeScript decorators para métodos de acesso

Accessor decorators funcionam de maneira semelhante a Property decorators, mas têm um **terceiro parâmetro adicional**. Em nosso exemplo, é o Property descriptor de um cliente. Quando aplicamos um Accessor decorator, ele altera o valor do Property descriptor. O código abaixo mostra como mudar o valor booleano de `enumerable`:

```typescript
const enumerable = (value: boolean
 
) => { 
  return (target: any, propertyKey: string, descriptor: PropertyDescriptor) => { 
    descriptor.enumerable = value; 
  }; 
};
```

Agora, aplicando o decorator, temos o seguinte código:

```typescript
class Cliente { 
  primeiroNome: string = "Julia"; 
  ultimoNome: string = "Silva"; 
 
  @enumerable(true) 
  get nomeCompleto() { 
    return `${this.primeiroNome} ${this.ultimoNome}`; 
  } 
}
```

## Parameter decorators: TypeScript decorators para parâmetros

**Parameter Decorators** no TypeScript têm três parâmetros: a função do construtor da classe, o nome do método e o índice do parâmetro. Embora o decorator não permita alterar o parâmetro diretamente, ele é útil para **validação**. Por exemplo, você pode verificar o índice do parâmetro com o seguinte código:

```typescript
function logParameter(target: Object, propertyKey: string, parameterIndex: number) { 
    console.log(`Decorating parameter ${parameterIndex} of ${propertyKey}`); 
}
```

Aplicação do decorator de parâmetro:

```typescript
class Exemplo { 
    testMethod(param0: any, @logParameter param1: any) {} 
}
```

Dica Ideal para sites estáticos e outras aplicações: com o [Deploy Now](https://www.ionos.com/hosting/deploy-now "Deploy Now - IONOS") da IONOS, você se beneficia de uma configuração rápida, de um staging simples e de fluxos de trabalho perfeitamente ajustados. Encontre o modelo ideal para as suas necessidades.


This is a markdown version of: [https://www.ionos.com/pt-br/digitalguide/sites-de-internet/desenvolvimento-web/typescript-decorators/](https://www.ionos.com/pt-br/digitalguide/sites-de-internet/desenvolvimento-web/typescript-decorators/) for AI/LLM consumption.