<h2>O que são Decorators em TypeScript?</h2>
<p>Decorators são uma funcionalidade experimental do TypeScript que permite adicionar metadados e modificar comportamentos de classes, métodos, propriedades e parâmetros em tempo de execução. Eles funcionam como funções que envolvem declarações, permitindo reutilizar lógica de forma elegante e declarativa. Essa é uma feature poderosa, especialmente quando combinada com reflection, tornando possível criar frameworks sofisticados como o NestJS.</p>
<p>Para usar decorators, você deve habilitar a flag <code>experimentalDecorators</code> no <code>tsconfig.json</code>. Existem cinco tipos principais: class decorators, method decorators, accessor decorators, property decorators e parameter decorators. Cada um opera em um nível diferente da hierarquia do código, permitindo controle fino sobre metadados e modificações.</p>
<pre><code class="language-json">{
"compilerOptions": {
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"target": "ES2020",
"lib": ["ES2020"]
}
}</code></pre>
<h2>Metadata e Reflection com reflect-metadata</h2>
<p>Reflection é a capacidade de um programa inspecionar sua própria estrutura em tempo de execução. A biblioteca <code>reflect-metadata</code> estende o Object global com métodos que permitem armazenar e recuperar metadados arbitrários. Isso é essencial para frameworks que precisam entender tipos e comportamentos dinamicamente. Instale com <code>npm install reflect-metadata</code>.</p>
<p>O decorator com <code>emitDecoratorMetadata</code> captura informações de tipo automaticamente. Você pode então usar <code>Reflect.getMetadata()</code> para recuperar essas informações. No exemplo abaixo, criamos um decorator que registra tipos de parâmetros:</p>
<pre><code class="language-typescript">import 'reflect-metadata';
function LogTypes(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
const types = Reflect.getMetadata('design:paramtypes', target, propertyKey);
const returnType = Reflect.getMetadata('design:returntype', target, propertyKey);
console.log(Método: ${propertyKey});
console.log(Tipos dos parâmetros:, types);
console.log(Tipo de retorno:, returnType);
return descriptor;
}
class Usuario {
@LogTypes
saudar(nome: string, idade: number): string {
return Olá ${nome}, você tem ${idade} anos;
}
}
const usuario = new Usuario();
usuario.saudar('João', 30);
// Output: Método: saudar, Tipos: [String, Number], Tipo de retorno: String</code></pre>
<h2>Decorators Prático: Validação e Autorização</h2>
<p>Decorators são especialmente úteis para validação e autorização em controladores. No mundo real, é comum validar dados de entrada ou verificar permissões antes de executar um método. Vamos criar decorators reutilizáveis que resolvem problemas comuns:</p>
<pre><code class="language-typescript">import 'reflect-metadata';
// Decorator para validar email
function ValidateEmail(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
const método = descriptor.value;
descriptor.value = function(...args: any[]) {
const email = args[0];
if (!email.includes('@')) {
throw new Error('Email inválido');
}
return método.apply(this, args);
};
return descriptor;
}
// Decorator para verificar autenticação
function Autenticado(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
const método = descriptor.value;
descriptor.value = function(...args: any[]) {
const usuarioLogado = (this as any).usuario;
if (!usuarioLogado) {
throw new Error('Usuário não autenticado');
}
return método.apply(this, args);
};
return descriptor;
}
class ServicoEmail {
usuario: string | null = 'joao@example.com';
@Autenticado
@ValidateEmail
enviarEmail(email: string, mensagem: string): void {
console.log(Email enviado para ${email}: ${mensagem});
}
}
const servico = new ServicoEmail();
servico.enviarEmail('maria@example.com', 'Olá!');</code></pre>
<h2>Decorators no NestJS: Aplicação Real</h2>
<p>NestJS é um framework Node.js que usa decorators extensivamente para criar aplicações modulares e escaláveis. Vamos criar um exemplo prático de um controlador com decorators de validação e autorização:</p>
<pre><code class="language-typescript">import { Controller, Get, Post, Body, Param, UseGuards } from '@nestjs/common';
import { IsEmail, IsString } from 'class-validator';
class CriarUsuarioDto {
@IsString()
nome: string;
@IsEmail()
email: string;
}
// Guard customizado com decorator
import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common';
@Injectable()
class AdminGuard implements CanActivate {
canActivate(context: ExecutionContext): boolean {
const request = context.switchToHttp().getRequest();
return request.user?.role === 'admin';
}
}
@Controller('usuarios')
export class UsuariosController {
private usuarios: any[] = [];
@Get(':id')
obterUsuario(@Param('id') id: string) {
return this.usuarios.find(u => u.id === id);
}
@Post()
@UseGuards(AdminGuard)
criarUsuario(@Body() dto: CriarUsuarioDto) {
const novoUsuario = { id: Date.now().toString(), ...dto };
this.usuarios.push(novoUsuario);
return novoUsuario;
}
}</code></pre>
<p>NestJS fornece decorators para métodos HTTP (<code>@Get</code>, <code>@Post</code>), injeção de dependência (<code>@Injectable</code>), validação automática com <code>class-validator</code>, e guards para autorização. A biblioteca <code>class-transformer</code> complementa isso, permitindo transformar dados em instâncias de classes com validação integrada.</p>
<h2>Conclusão</h2>
<p>Decorators em TypeScript, combinados com reflection e metadata, são ferramentas poderosas para criar código limpo, reutilizável e auto-documentado. Eles permitem separar concerns como validação, autenticação e logging da lógica de negócio. No contexto do NestJS, tornam-se absolutamente essenciais para estruturar aplicações enterprise. O aprendizado de decorators é fundamental para dominar frameworks modernos e escrever código profissional em TypeScript. Pratique criando seus próprios decorators antes de usar os prontos, isso consolida o entendimento.</p>
<h2>Referências</h2>
<ul>
<li><a href="https://www.typescriptlang.org/docs/handbook/decorators.html" target="_blank" rel="noopener noreferrer">TypeScript Handbook: Decorators</a></li>
<li><a href="https://www.npmjs.com/package/reflect-metadata" target="_blank" rel="noopener noreferrer">reflect-metadata - npm</a></li>
<li><a href="https://docs.nestjs.com/" target="_blank" rel="noopener noreferrer">NestJS Documentation</a></li>
<li><a href="https://www.npmjs.com/package/class-validator" target="_blank" rel="noopener noreferrer">class-validator - npm</a></li>
<li><a href="https://github.com/getify/You-Dont-Know-JS" target="_blank" rel="noopener noreferrer">You Don't Know JS Yet: Scope & Closures</a></li>
</ul>