NestJS 认识装饰器(Decorator)
从 TypeScript 装饰器基础出发,梳理 NestJS 中类、方法、参数装饰器的典型用法,并通过示例说明其在路由声明、依赖注入和参数提取中的作用。
在 NestJS 中,装饰器(Decorator) 是其核心特性的基础,理解装饰器是顺畅使用 NestJS 的前提。
📌 什么是装饰器?
装饰器是 TypeScript 提供的一种特殊声明,本质上是一个 函数,它可以附加到类、方法、属性或参数上,在不修改原始代码结构的情况下,以声明式的方式注入元数据或增强行为。
语法:使用 @ 符号 + 函数名,写在目标项的上方。
@Controller('users') // 装饰器 export class UserController {}
🧠 TypeScript 装饰器类型
NestJS 主要用到以下四种装饰器:
| 类型 | 作用目标 | 示例 |
|---|---|---|
| 类装饰器 | 类构造函数 | @Controller(), @Injectable(), @Module() |
| 方法装饰器 | 实例方法 | @Get(), @Post(), @UseGuards() |
| 参数装饰器 | 方法参数 | @Req(), @Res(), @Body(), @Param(), @Query() |
| 属性装饰器 | 类的属性 | 较少直接使用(常用于自定义元数据) |
🏗️ NestJS 中装饰器的作用
NestJS 大量依赖装饰器来构建应用结构,实现了 声明式编程 与 依赖注入:
- 定义路由:
@Get(),@Post()等告诉 HTTP 服务器,具体方法应处理哪个路径的请求。 - 标记可注入类:
@Injectable()让类能被 Nest IoC 容器管理。 - 组装模块:
@Module()将控制器、服务、导入导出等组合成模块。 - 提取请求数据:
@Body(),@Param(),@Query()直接从 request 对象中获取对应部分。 - 附加元数据:例如
@SetMetadata()可为方法/类设置自定义元数据,供守卫或拦截器读取。
✏️ 简单示例
@Controller('products') // 类装饰器:基路径 /products export class ProductController { constructor(private productService: ProductService) {} // 依赖注入 @Get(':id') // 方法装饰器:GET /products/123 findOne(@Param('id') id: string) { // 参数装饰器:提取 id return this.productService.findById(id); } @Post() // 方法装饰器:POST /products create(@Body() createDto: CreateProductDto) { // 参数装饰器:提取请求体 // ... } }
🔧 如何自定义装饰器?
NestJS 提供 createParamDecorator 工厂函数,可以创建自己的参数装饰器:
import { createParamDecorator, ExecutionContext } from '@nestjs/common'; export const User = createParamDecorator( (data: unknown, ctx: ExecutionContext) => { const request = ctx.switchToHttp().getRequest(); return request.user; // 假设身份验证后 user 被挂载到 request } ); // 在控制器中使用 @Get('profile') getProfile(@User() user) { // 直接注入当前用户对象 console.log(user); }
💎 总结
- 装饰器 = 给类/方法/参数打标签的函数。
- NestJS 利用装饰器实现 声明式路由、依赖注入、数据提取,让代码更简洁优雅。
- 前置知识:需要熟悉 TypeScript 中的装饰器概念(虽然 TS 默认开启
experimentalDecorators)。 - 掌握内置装饰器的用法后,可以轻松实现自定义装饰器,大幅提升代码复用性。
如果你对某一类装饰器的具体实现原理感兴趣,我可以进一步展开。