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

NestJS如何定义支持动态ID为键、值为对象数组的DTO结构

NestJS 实现动态顶层键结构的DTO定义

处理无固定名的动态顶层键,核心是通过TypeScript索引签名定义结构,结合NestJS默认集成的class-validator、class-transformer就能完成类型约束和运行时校验,具体实现步骤如下:

1. 定义数组项的基础DTO

首先定义动态键对应数组里的单个业务对象结构,注意修正你示例里surname后的笔误(原示例里写的是.,实际属性赋值用:):

import { IsString, IsNotEmpty } from 'class-validator';

export class BusinessItemDto {
  @IsString()
  @IsNotEmpty()
  name: string;

  @IsString()
  @IsNotEmpty()
  surname: string;
}

2. 定义顶层动态键结构

根据业务场景选择对应写法:

场景1:仅需TS类型约束,不需要接口运行时校验

如果是内部方法传参、不需要对入参做自动校验,直接用TS接口定义索引签名即可:

interface UserIdBusinessMap {
  // 键为动态生成的字符串格式用户ID,值为业务对象数组
  [userId: string]: BusinessItemDto[]
}

这种写法下,你可以直接通过const data: UserIdBusinessMap = { 123456: [{name: 'lorem', surname: 'lorem'}] }的格式赋值,TS会自动做类型检查。

场景2:需要接口入参运行时校验(配合NestJS ValidationPipe)

如果是Controller层接收前端请求、需要自动校验参数格式,需要定义可被实例化的class,配合转换逻辑保证嵌套校验生效:

import { IsObject, Validate } from 'class-validator';
import { plainToInstance } from 'class-transformer';
import { BusinessItemDto } from './business-item.dto';
import { ValidatorConstraint, ValidatorConstraintInterface } from 'class-validator';

// 可选:自定义校验器,校验顶层动态键符合用户ID格式
@ValidatorConstraint({ name: 'userIdKeyValidate', async: false })
class UserIdKeyValidate implements ValidatorConstraintInterface {
  validate(value: unknown) {
    if (typeof value !== 'object' || value === null) return false;
    // 这里可以自定义ID规则,示例为校验ID是纯数字字符串
    return Object.keys(value).every(key => /^\d+$/.test(key));
  }
  defaultMessage() {
    return '顶层键必须为合法的数字格式用户ID';
  }
}

export class DynamicMapDto {
  @IsObject()
  @Validate(UserIdKeyValidate)
  [userId: string]: BusinessItemDto[];

  // 配合ValidationPipe的transform选项做嵌套类型转换
  static transform(value: unknown) {
    if (typeof value !== 'object' || value === null) return value;
    const instance = new DynamicMapDto();
    for (const [userId, itemList] of Object.entries(value)) {
      instance[userId] = plainToInstance(BusinessItemDto, itemList as any[]);
    }
    return instance;
  }
}

3. Controller层使用示例

开启ValidationPipe的自动转换即可自动完成校验:

import { Controller, Post, Body, ValidationPipe } from '@nestjs/common';
import { DynamicMapDto } from './dto/dynamic-map.dto';

@Controller('business')
export class BusinessController {
  @Post('batch-update')
  batchUpdate(
    @Body(new ValidationPipe({ transform: true }))
    body: DynamicMapDto
  ) {
    // 直接通过用户ID访问对应数组即可,比如 body['123456']
    return body;
  }
}

内容的提问来源于stack exchange,提问作者Fabrizio Manna

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 19:57:15