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

NestJS CQRS:如何简洁地将DTO对象作为命令构造参数传递

解决方案

问题出在两个核心点:一是之前泛型参数错误地使用了子类自身,导致类型不匹配且会复制payload的所有属性;二是直接用Object.assign会把payload里的冗余字段(比如type)也赋值给命令实例,同时子类声明的未初始化属性会错误覆盖传入的有效值。

可以通过修改抽象命令类的构造函数,仅复制子类实例的自有属性来解决,既过滤多余字段,又确保属性正确赋值:

export class AbstractCommand<T> implements ICommand {
    constructor(args: T) {
        // 获取当前子类实例的自有属性(即子类中声明的属性)
        const ownPropertyNames = Object.getOwnPropertyNames(this);
        // 仅复制args中与子类自有属性匹配的键值对
        ownPropertyNames.forEach(prop => {
            if (Object.prototype.hasOwnProperty.call(args, prop)) {
                // 类型断言绕过readonly编译检查,构造函数内允许赋值
                (this as Record<string, unknown>)[prop] = (args as Record<string, unknown>)[prop];
            }
        });
    }
}

// 子类保持原有定义,泛型参数改为传入的Payload类型
export class CreateProductTypeACommand extends AbstractCommand<Payload> {
    public readonly name?: string;
}

使用示例:

const payload: Payload = { type: 'typeA', name: 'Product A' };
const command = new CreateProductTypeACommand(payload);
// command 仅包含name属性,值为'Product A',无type字段

原理说明

  1. 泛型修正:将抽象类的泛型参数改为实际传入的Payload类型,确保类型匹配且符合初始化逻辑。
  2. 属性过滤:通过Object.getOwnPropertyNames(this)获取子类声明的所有自有属性,只复制payload中对应的属性,自动过滤type这类冗余字段。
  3. 避免覆盖:主动赋值匹配的属性,不会被子类未初始化的undefined覆盖,同时保留readonly的编译时约束。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 09:25:01