You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NestJS中如何基于父类B的type属性验证子类A的content?

问题描述

在NestJS中使用class-validator进行嵌套对象验证时,类A作为类B中属性a的类型。需要在类A的content属性的自定义验证装饰器IsValidContent中,获取类B的type属性值,以此判断content是否符合对应类型规则:当type为X时验证content为Content1类型,为Y时验证为Content2类型。但当前代码尝试获取父类type属性失败,求可行的实现方法。

相关代码如下:

class Content1 {}

class Content2 {}

class A {
  @IsValidContent()
  content: Content1 | Content2;
}

class B {
  @Type(() => A)
  @ValidateNested({ each: true })
  a: A;

  type: string;
}

export function IsValidContent(validationOptions?: ValidationOptions) {
  return (object: Object, propertyName: string) => {
    registerDecorator({
      name: "isValidContent",
      target: object.constructor,
      propertyName,
      constraints: [],
      options: validationOptions,
      validator: {
        validate(value: any, args: ValidationArguments) {
          const type = args.object["type"]; // 无法获取父类的type属性
          switch (type) {
            case "X":
              return isValidType(value, Content1);
            case "Y":
              return isValidType(value, Content2);
            default:
              return false;
          }
        },
      },
    });
  }
}
解决方案

问题根源

嵌套验证场景下,args.object指向的是当前被验证的类A实例,而type属性属于父类B的实例,因此直接通过args.object["type"]无法获取到目标值。

实现方法

利用ValidationArguments提供的root属性,它指向整个验证流程的根对象(也就是类B的实例),通过它可以直接读取type属性。同时补充isValidType的具体实现逻辑,使用class-validator和class-transformer的工具方法来判断类型是否匹配。

修改后的完整代码如下:

import { registerDecorator, ValidationArguments, ValidationOptions, validateSync } from 'class-validator';
import { plainToInstance } from 'class-transformer';

class Content1 {}

class Content2 {}

class A {
  @IsValidContent()
  content: Content1 | Content2;
}

class B {
  @Type(() => A)
  @ValidateNested({ each: true })
  a: A;

  type: string;
}

// 辅助函数:验证值是否符合指定类的结构要求
function isValidType(value: any, targetClass: any): boolean {
  const instance = plainToInstance(targetClass, value);
  const errors = validateSync(instance);
  return errors.length === 0;
}

export function IsValidContent(validationOptions?: ValidationOptions) {
  return (object: Object, propertyName: string) => {
    registerDecorator({
      name: "isValidContent",
      target: object.constructor,
      propertyName,
      constraints: [],
      options: validationOptions,
      validator: {
        validate(value: any, args: ValidationArguments) {
          // 通过root属性获取根对象(B的实例),进而拿到type
          const rootObj = args.root as B;
          const type = rootObj.type;
          
          switch (type) {
            case "X":
              return isValidType(value, Content1);
            case "Y":
              return isValidType(value, Content2);
            default:
              return false;
          }
        },
      },
    });
  }
}

注意事项

如果类B中的a是数组类型,args.root依然指向B的实例,不会受数组嵌套影响,因此上述代码同样适用。


内容的提问来源于stack exchange,提问作者Lang Minh Nguyên

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 22:32:36