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

清洁架构下Node.js应用领域实体部分类型构建与定位咨询

针对Clean Architecture下食谱应用的两个问题解答

1. 优化部分类型构建的方案

以下几种方案可以简化你的部分类型定义和转换流程:

  • 利用TypeScript内置工具类型:直接用Pick/Omit基于完整的RecipeEntity生成部分类型,无需重复定义字段:
    // 从RecipeEntity中挑选需要的字段
    type GetRecipe = Pick<RecipeEntity, 'id' | 'title' | 'summary'> & {
      ingredients: Pick<IngredientEntity, 'name' | 'quantity'>[];
    };
    
    // 或者排除不需要的字段
    type GetRecipe = Omit<RecipeEntity, 'createdAt' | 'updatedAt' | 'internalNotes'>;
    
  • 复用基础DTO结构:如果有多个类似的部分类型,可以先定义公共基础DTO,再扩展出特定类型:
    // 基础公共字段
    type RecipeBaseDTO = Pick<RecipeEntity, 'id' | 'title' | 'summary'>;
    // 带配料的详情DTO
    type GetRecipeWithIngredients = RecipeBaseDTO & {
      ingredients: Pick<IngredientEntity, 'name' | 'quantity'>[];
    };
    // 仅基础信息的列表DTO
    type RecipeListItem = RecipeBaseDTO;
    
  • 引入映射器模式:创建专门的映射函数集中处理实体到DTO的转换,避免在多处重复编写转换逻辑:
    // 可以放在用例层的mapper模块,比如/use-cases/recipe/mappers/RecipeMapper.ts
    export const mapRecipeToGetRecipe = (recipe: RecipeEntity): GetRecipe => {
      return {
        id: recipe.id,
        title: recipe.title,
        summary: recipe.summary,
        ingredients: recipe.ingredients.map(ing => ({
          name: ing.name,
          quantity: ing.quantity
        }))
      };
    };
    
  • 结合GraphQL动态字段选择:利用GraphQL的info参数获取客户端请求的字段,在数据层只查询需要的字段,同时动态生成返回结构。比如解析请求字段后针对性地映射数据,既减少冗余查询,又能灵活适配客户端需求。

2. GetRecipe接口在Clean Architecture中的合理位置

根据Clean Architecture的依赖倒置原则和分层规则,推荐把GetRecipe放在用例层,具体位置可以是:

  • /use-cases/recipe/dto/GetRecipe.ts

原因如下:

  • 领域层是核心,只负责定义完整的业务实体(RecipeEntity),不应该依赖外部的输出格式需求。GetRecipe是为了适配客户端的精简数据需求,属于业务用例的输出模型,而非核心业务实体。
  • 用例层定义了业务规则的输入输出边界,适配器层(比如你的GraphQL API)依赖用例层的输出模型来构建响应,符合“外层依赖内层”的分层原则。
  • 如果后续新增其他适配器(比如REST API),用例层的GetRecipe可以作为统一的输出标准,各适配器只需做少量适配即可使用,避免重复定义类似的类型。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 05:22:27