NestJS class-validator嵌套对象校验 启动报AddressRequest初始化错误
错误原因
这个报错是类加载顺序导致的引用错误:
- ES6中
class声明不存在变量提升,在代码执行到类定义语句前,对应类处于暂时性死区,直接访问会抛出Cannot access 'Xxx' before initialization错误。 - 你的代码中
DestinationRequest定义在AddressRequest之前,但类装饰器(包括这里的@Type、@ValidateNested)会在模块加载、类定义阶段就执行参数求值,此时下方的AddressRequest还未完成初始化,因此触发引用错误。 - 额外问题:原有代码中
AddressRequest内的geolocation字段仅添加了@IsOptional()装饰器,没有嵌套校验规则,即使解决了启动报错,传入非法格式的经纬度参数也不会被拦截。
修复方案
- 调整DTO定义顺序,将被依赖的嵌套类
AddressRequest、GeolocationRequest放在外层类DestinationRequest之前定义,保证装饰器执行时被引用的类已经完成初始化。 - 补全
geolocation字段的嵌套校验逻辑,保证多层嵌套对象的参数都能被正常校验。
修复后的完整代码如下:
import { Type } from "class-transformer" import { IsObject, IsOptional, IsString, MaxLength, ValidateNested, IsNumber } from "class-validator" // 经纬度嵌套DTO,优先定义 export class GeolocationRequest { @IsNumber() latitude: number @IsNumber() // 注意原代码字段拼写错误:正确拼写为longitude,若需兼容旧参数可保留logitude字段 longitude: number } // 地址嵌套DTO,在外层引用它的DTO之前定义 export class AddressRequest { @IsString() @MaxLength(50, { message: 'city should be only 50 letters' }) city: string @IsString() @MaxLength(25, { message: 'country should be only 25 letters' }) country: string @IsString() @IsOptional() @MaxLength(100, { message: 'detail should be only 100 letters' }) detail: string @IsOptional() @ValidateNested() @Type(() => GeolocationRequest) geolocation: GeolocationRequest } // 外层请求DTO,最后定义 export class DestinationRequest { @IsString() @MaxLength(2, { message: 'should be only of 2 letters' }) lang: string @IsString() @MaxLength(50, { message: 'should be only of 50 letters' }) name: string @IsOptional() @ValidateNested() @IsObject() @Type(() => AddressRequest) address: AddressRequest @IsString() @IsOptional() content: string }
调整后重新启动应用即可正常运行,所有层级的嵌套参数都会按照定义的规则完成校验。
内容的提问来源于stack exchange,提问作者Simple Fellow
相关产品推荐
相关产品推荐

