基于数值枚举的Visitor模式:寻求TypeScript更优实现方案
用Visitor模式确保枚举新增值的全场景处理(TypeScript优化方案)
需求背景
我希望借助Visitor模式,确保新增枚举值时所有相关业务场景都能被完整处理,避免遗漏。现有枚举定义如下:
export enum ActionItemTypeEnum { AccountManager = 0, Affiliate = 4, }
当前实现方式
目前我手动维护Visitor接口和访问函数,新增枚举值时需要手动更新接口和switch分支——虽然缺失分支会触发编译错误,但整体维护成本较高:
interface IActionItemTypeVisitor<T> { accountManager(value: ActionItemTypeEnum.AccountManager): T; affiliate(value: ActionItemTypeEnum.Affiliate): T; } // 缺失枚举分支时会触发编译错误 const visitActionItemType = <T>(value: ActionItemTypeEnum, visitor: IActionItemTypeVisitor<T>) => { // eslint-disable-next-line switch (value) { case ActionItemTypeEnum.None: return visitor.none(value); case ActionItemTypeEnum.AccountManager: return visitor.accountManager(value); } }; // 示例:实现Visitor接口处理权限逻辑 const permission = visitActionItemType(this.type, new ActionItemPermissionVisitor())
我想知道有没有更地道的TypeScript解决方案,减少手动维护的工作量。
优化后的最终解决方案
通过TypeScript的映射类型和枚举的反向映射特性,可以实现枚举值与Visitor方法的自动关联,新增枚举值时只需实现对应的Visitor方法即可,无需手动修改访问函数:
1. 自动生成Visitor类型
利用keyof和Uncapitalize工具类型,根据枚举的键自动生成Visitor接口的方法签名:
export type IActionItemTypeVisitor<T> = { [K in keyof typeof ActionItemTypeEnum as Uncapitalize<K>]: (value: (typeof ActionItemTypeEnum)[K]) => T; };
2. 通用访问函数
通过枚举的反向映射获取枚举键,自动转换为小驼峰方法名,调用对应的Visitor方法:
export const visitActionItemType = <T>(value: ActionItemTypeEnum, visitor: IActionItemTypeVisitor<T>): T => { const key: string = ActionItemTypeEnum[value]?.[0].toLowerCase() + ActionItemTypeEnum[value]?.substring(1); return visitor[key]?.(value); };
3. Visitor实现示例
实现自动生成的Visitor类型,新增枚举值时只需添加对应方法即可:
export class ActionItemVisitor implements IActionItemTypeVisitor<string> { public accountManager(value: ActionItemTypeEnum.AccountManager): string { return 'AccountManager'; } public affiliate(value: ActionItemTypeEnum.Affiliate): string { return 'Affiliate'; } } // 使用示例 const result: string = visitActionItemType(ActionItemTypeEnum.AccountManager, new ActionItemVisitor());
内容的提问来源于stack exchange,提问作者kemsky
相关产品推荐
相关产品推荐

