如何创建一个自定义的NestJs装饰器来继承@Body()或@Param()装饰器?

11

我正在使用NestJs,在我的许多控制器中我使用:

@Post(":id")
public create(
    @Param('id', new ParseIntPipe()) id: number, 
    @Body(new ValidationPipe({transform: true})) myData: MyClass) {
        // ... 
    }

我想通过创建自定义装饰器来简化我的代码,例如:

@Bind() => @Body(new ValidationPipe({transform: true}))

或者

@Id() => @Param('id', new ParseIntPipe())

那么,代码将比之前更加干净:
@Post(":id")
public create(@Id() id: number, @Bind() myData: MyClass) {
    // ... 
}

如何正确继承这些装饰器呢?

谢谢

2个回答

13

由于装饰器只是普通的函数,您可以创建一个返回所调用装饰器的函数:

decorators.ts

import { Body, Param, ParseIntPipe, ValidationPipe } from '@nestjs/common';

export const Bind = () => Body(
  new ValidationPipe({transform: true}),
);

export const Id = () => Param('id', new ParseIntPipe());

然后将它们用作装饰器:

import { Id, Bind } from './decorators';

// ... 

@Post(":id")
public create(@Id() id: number, @Bind() myData: MyClass) {
    // ... 
}

2
我正在回答问题,同时这个问题也出现了,哈哈,我可以确认这确实有效。 - antirealm
给定的示例对我不起作用,因为我有一个全局验证管道。我在这里的gist中详细说明了所有内容:https://gist.github.com/josephdpurcell/9af97c36148673de596ecaa7e5eb6a0a。 - josephdpurcell

1
请使用以下代码自定义nestjs的body装饰器来验证请求。
export const RBody = createParamDecorator(
  async (value: any, ctx: ExecutionContext) => {
    // extract headers
    const reqBody = ctx.switchToHttp().getRequest().body;
    // Convert headers to DTO object
    const dto = plainToInstance(value, reqBody);
    return await validateOrReject(dto).then(
      (res) => {
        console.log(`Header validated successfully..${res}`);
        return dto;
      },
      (err) => {
        if (err.length > 0) {
          //Get the errors and push to custom array
          const validationErrors = err.map((obj, key) =>
            Object.values(obj.constraints)
          );
          throwException(validationErrors);
        }
      },
    );
    return dto;
  },
);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接