是否可以在 NestJs 中为 DTO 进行继承?
Posted
技术标签:
【中文标题】是否可以在 NestJs 中为 DTO 进行继承?【英文标题】:Is it possible to do inheritance for DTOs in NestJs? 【发布时间】:2020-05-30 03:38:59 【问题描述】:我有一个 NestJs Get 控制器,用于搜索员工列表。
@Controller('employee')
export class EmployeeController
private logger = new Logger('EmployeeController');
constructor(private employeeService:EmployeeService)
@Get()
@UsePipes(new ValidationPipe( transform: true ))
getEmployees(
@Query() filter:GetEmployeesFilterDto
):Promise<Employee[]>
console.log(JSON.stringify(filter), filter.batch);
return this.employeeService.getEmployees(filter);
为了支持分页,该方法接受一个过滤器DTO来接受批量大小和页码等参数。看到这将如何成为其他 DTO 类的通用参数,我想到了创建一个基本过滤器 DTO:
export class BaseQueryFilterDto
@IsOptional()
@IsInt()
@UsePipes(ParseIntPipe)
batch:number;
@IsOptional()
@IsInt()
@UsePipes(ParseIntPipe)
skip:number;
然后为 GetEmployeesFilterDto 继承这个 DTO:
export class GetEmployeesFilterDto extends BaseQueryFilterDto
@IsOptional()
@IsNotEmpty()
search:string;
@IsOptional()
primarySupervisorId:string;
运行以下请求http://localhost:3000/employee?batch=30会抛出以下异常:
[Nest] 27920 - 02/14/2020, 6:29:54 PM [ExceptionsHandler] Cannot assign to read only property 'batch' of object '#<GetEmployeesFilterDto>' +606974ms
TypeError: Cannot assign to read only property 'batch' of object '#<GetEmployeesFilterDto>'
at _loop_1 (C:\ng-proj\nestjs-tutorial\node_modules\class-transformer\TransformOperationExecutor.js:242:47)
at TransformOperationExecutor.transform (C:\ng-proj\nestjs-tutorial\node_modules\class-transformer\TransformOperationExecutor.js:260:17)
at ClassTransformer.plainToClass (C:\ng-proj\nestjs-tutorial\node_modules\class-transformer\ClassTransformer.js:17:25) at Object.plainToClass (C:\ng-proj\nestjs-tutorial\node_modules\class-transformer\index.js:20:29)
at ValidationPipe.transform (C:\ng-proj\nestjs-tutorial\node_modules\@nestjs\common\pipes\validation.pipe.js:55:41)
at transforms.reduce (C:\ng-proj\nestjs-tutorial\node_modules\@nestjs\core\pipes\pipes-consumer.js:15:33)
at process._tickCallback (internal/process/next_tick.js:68:7)
但是,当我像这样将所有属性从超类移动到 GetEmployeesFilterDto 时:
export class GetEmployeesFilterDto extends BaseQueryFilterDto
@IsOptional()
@IsNotEmpty()
search:string;
@IsOptional()
primarySupervisorId:string;
//Moved from BaseQueryFilterDto
@IsOptional()
@IsInt()
@UsePipes(ParseIntPipe)
batch:number;
@IsOptional()
@IsInt()
@UsePipes(ParseIntPipe)
skip:number;
请求成功运行。 我在这里遗漏了什么,或者我不能在 NestJs 中实现对控制器 DTO 的继承吗?
【问题讨论】:
这看起来像是来自堆栈跟踪的class-transformer
问题。您可以尝试联系class-transformer
寻求帮助吗?
为什么你要定义的属性有@UsePipes()
?该装饰器仅适用于控制器、控制器方法和控制器方法参数
@JayMcDoniel,如果没有 ParseIntPipe,IsInt 验证将失败,因为来自查询字符串的所有值都是字符串。也许这是对 DTO 属性进行 parseInt 的错误方法。抱歉,我对 NestJs 很陌生
@vinnyo 为什么不使用来自class-trasnformer
的@Type()
转换作为验证过程的一部分,这样在验证后它也将被解析并且您不会在a 中使用@UsePipe()
奇怪的地方?
@JayMcDoniel,最初,我尝试使用@Type()
,但遇到了验证错误。但我现在意识到我不应该用@Type()
添加@IsInt()
验证装饰器。将用答案更新我的帖子。非常感谢!
【参考方案1】:
感谢@JayMcDoniel 指出我不应该在属性上使用@UsePipes()
。
这是适合我的解决方案。
export class BaseQueryFilterDto
@IsOptional()
@Type(() => Number)
batch:number;
@IsOptional()
@Type(() => Number)
skip:number;
【讨论】:
以上是关于是否可以在 NestJs 中为 DTO 进行继承?的主要内容,如果未能解决你的问题,请参考以下文章