如何在管道/拦截器等中使用DTO

时间:2020-05-12 18:36:16

标签: typescript nestjs

比方说,我的控制器上有一个方法如下:

    @Post('register')
    @UseInterceptors(ClassSerializerInterceptor)
    @UsePipes(...[
        new ValidationPipe({ whitelist: true, forbidNonWhitelisted: true }),
        LoginCodeValidationPipe,
    ])
    public async register(@Body() user: RegisterUserDto): Promise<User> {
        // register logic
    }

这里LoginCodeValidationPipe是一个验证管道。看起来像这样:

@Injectable()
export class LoginCodeValidationPipe implements PipeTransform {
    constructor(
        private readonly cacheService: CacheService,
    ) {}

    public async transform(loginInfo: LoginDto) {
        const loginCode: string = await this.cacheService.get(KeyConverter.phoneLoginCode(loginInfo.phone));
        if (loginCode === loginInfo.loginCode) {
            return loginInfo;
        } else {
            throw new HttpException('Error message', HttpStatus.FORBIDDEN);
        }
    }
}

问题源于我希望管道可以重复使用并且我相信它们应该可以重复使用的事实。

因此,这里重要的是LoginDto具有RegisterUserDto中存在的所有字段或更精确的字段,LoginDtoRegisterUserDto的子类。

因此,传递到管道中的数据的类型为RegisterUserDto(事实参数的类型),但是管道的形式参数的类型不同(LoginDto),这可能会使cos混乱这些类型似乎没有关联,至少目前尚不清楚。

如何最好避免这种情况?!

我的建议:

如果我将dto传递给管道,则dto应该为此管道接口实现一个特定的接口(在这种情况下,类似ILoginCodeValidation)。接下来,管道的形式参数的类型(在这种情况下为LoginDto)也应实现ILoginCodeValidation

但是,应该为管道参数选择什么名称而不是loginInfo?我认为这里可以使用泛型。但是现在我似乎还不知道怎么做。

0 个答案:

没有答案