打字稿:一次构建一个对象的模式

时间:2021-06-16 08:24:11

标签: javascript node.js reactjs typescript types

这种情况在创建复杂的对象插入数据库时​​尤为常见。我可能有一个需要 20 个字段的对象,每个字段都来自其他地方。

interface Cat {hair: HairType, name: string, ...20 other properties}
function insertCatIntoDB(cat: Cat){...}

function createCatForUser(userType: UserType){
  const newCat: Partial<Cat> = {};
  newCat.name = getNewCatNameForUserType(userType);
  ...business logic involving the setting of the other properties
  insertCatIntoDB(newCat); // Problem: newCat is Partial<Cat> 
                           // instead of Cat despite having assigned all of the properties

}

我看到了几种解决方法。

  1. 将每个属性的“获取”重构为一个新函数,然后调用类似的东西
insertCatIntoDB({hair: getHairByUserType, name: getNameByUserType, ...})

但是,如果创建属性所需的业务逻辑相对简单,那么您将创建 20 个函数,每个函数可能有 3 行代码,这些函数只会被调用一次,这对于可读性来说不是很好。

  1. 类似,但不是创建新函数,而是在选项“内部”进行操作,例如

insertCatIntoDB({name: userType === UserType.girl ? 'cookie' : (userType === userType.boy ? 'tiger' : 'persian'), ...}) 但即使在这个具有非常简单逻辑的示例中,这也会很快变得笨拙且难以阅读。

  1. 做一些像insertCatIntoDB(newCat as Cat)

但这不是类型检查。

我正在寻找有关处理这些情况的更好方法的建议。

1 个答案:

答案 0 :(得分:1)

当我查看您界面中的属性数量并根据您的重构想法时,我对此有几个想法:

  • 根据Interface segregation principles将此接口拆分为更小的接口。我们可以使用 Information experts principleHigh cohesion principle 来创建几个接口,这些接口包含几个高内聚属性的信息。这样,不用创建20个函数来按类型获取属性,只需要几个实例即可。

  • 使用工厂模式创建 getNameByUserType、getHairByUserType、getOtherAttributesByType 等...

  • 使用Builder模式初始化cat对象,将上述工厂注入到builder中(参考:https://refactoring.guru/design-patterns/builder)。例如:

    const cat = new CatBuilder()
     .byUserType(userType)
     .withGetByUserTypeFactory(GetByUserTypeFactory)
     .withHair()
     .withName()
     .(...other attributes...)
     .build();