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

如何在TypeScript单一Builder模式中实现创建/更新的条件运行时验证

Permission Builder重构方案(Node.js/TypeScript)

针对创建与更新操作的互斥约束,拆分出独立的buildForCreate()和buildForUpdate()方法是最直接且易维护的方案,避免单个build()方法中复杂的条件分支,同时让调用方明确当前操作类型,减少误操作。

重构后代码实现

import { CustomError } from "../../../shared";

export class PermissionBuilder {
    private id?: string;
    private name?: string;
    private module?: string;

    constructor() {}

    setId(id: string): PermissionBuilder {
        if (!id || !id.trim()) throw CustomError.badRequest('ID cannot be empty');
        this.id = id;
        return this;
    }

    setName(name: string): PermissionBuilder {
        if (!name || !name.trim()) throw CustomError.badRequest('Name cannot be empty');
        this.name = name;
        return this;
    }

    setModule(module: string): PermissionBuilder {
        if (!module || !module.trim()) throw CustomError.badRequest('Module cannot be empty');
        this.module = module;
        return this;
    }

    // 构建创建用Permission实例
    buildForCreate() {
        // 创建操作:禁止传入ID
        if (this.id !== undefined) {
            throw CustomError.badRequest('Create operation cannot specify ID');
        }
        // 创建操作:name和module为必填项
        if (!this.name || !this.name.trim()) {
            throw CustomError.badRequest('Name is required for create operation');
        }
        if (!this.module || !this.module.trim()) {
            throw CustomError.badRequest('Module is required for create operation');
        }

        return {
            id: this.id,
            name: this.name,
            module: this.module,
        };
    }

    // 构建更新用Permission实例
    buildForUpdate() {
        // 更新操作:ID为必填项
        if (!this.id || !this.id.trim()) {
            throw CustomError.badRequest('ID is required for update operation');
        }
        // 更新操作:至少提供name或module其中一个
        const hasValidName = this.name && this.name.trim();
        const hasValidModule = this.module && this.module.trim();
        if (!hasValidName && !hasValidModule) {
            throw CustomError.badRequest('At least one of name or module must be provided for update');
        }

        return {
            id: this.id,
            name: hasValidName ? this.name : undefined,
            module: hasValidModule ? this.module : undefined,
        };
    }
}

核心逻辑说明

  1. 操作类型明确区分:调用方必须调用对应操作的build方法,从根源上避免混淆创建/更新逻辑。
  2. 创建操作验证:
    • 强制id必须为undefined,防止创建时传入数据库自增ID或无效ID。
    • 校验name和module必须非空,确保创建的实例具备必要字段。
  3. 更新操作验证:
    • 强制id必须存在且非空,确保更新目标明确。
    • 校验name和module至少有一个有效字段,避免无意义的空更新。
    • 未提供的字段保持undefined,仓储层可通过判断undefined来跳过对应列的更新操作。

额外优化建议(可选)

如果需要在TypeScript层面强化类型约束,可以为创建和更新分别定义不同的返回类型:

type CreatePermission = {
    id?: never;
    name: string;
    module: string;
};

type UpdatePermission = {
    id: string;
    name?: string;
    module?: string;
};

// 对应修改build方法的返回类型
buildForCreate(): CreatePermission { /* ... */ }
buildForUpdate(): UpdatePermission { /* ... */ }

这样调用方在编译阶段就能发现错误(比如创建时传入id),进一步提升代码可靠性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.02 05:53:10