TypeScript中如何避免基于辨别符的switch分支语句?
用类型安全的映射表替代Switch分支重构代码
需求:移除switch分支语句,同时保留TypeScript类型安全,避免使用any类型。
原代码实现:
function translate(when: When): SomeCommonResultType { switch (when.object) { case "timespan": return translateTimeSpan(when); case "time": return translateTime(when); case "datespan": return translateDateSpan(when); case "date": return translateDate(when); } } type When = Timespan | Time | DateSpan | Date; export interface Timespan { readonly object: "timespan"; startTime: number; endTime: number; startTimezone?: string; endTimezone?: string; } function translateTimeSpan(when: Timespan): SomeCommonResultType { // ... } export interface Time { readonly object: "time"; time: number; timezone: string; } function translateTime(when: Time): SomeCommonResultType { // ... } export interface DateSpan { readonly object: "datespan"; startDate: string; endDate: string; } function translateDateSpan(when: DateSpan): SomeCommonResultType { // ... } export interface Date { readonly object: "date"; date: string; } function translateDate(when: Date): SomeCommonResultType { // ... }
用户原有映射表写法(存在any类型问题):
const TranslateWhenMap = new Map<string, any>([ ["timespan", translateTimeSpan], ["date", translateDate], ["datespan", translateDateSpan], ["time", translateTime], ]); function translate(when: When): SomeCommonResultType { return TranslateWhenMap.get(when.object)(when); }
类型安全的映射表重构方案
步骤1:定义严格类型的处理函数映射表类型
利用TypeScript的索引类型和条件类型,将When联合类型中的每个子类型与对应的处理函数关联:
// 定义映射表类型:键为When的object属性值,值为对应子类型的处理函数 type WhenHandlerMap = { [K in When['object']]: (when: Extract<When, { object: K }>) => SomeCommonResultType; };
步骤2:创建类型安全的映射表
用上述类型约束映射表,确保每个键对应的处理函数参数和返回值完全匹配:
const translateWhenMap: WhenHandlerMap = { timespan: translateTimeSpan, time: translateTime, datespan: translateDateSpan, date: translateDate, };
步骤3:重构translate函数
通过映射表直接调用对应处理函数,这里的as never是TypeScript的小技巧——编译器暂时无法自动推断when的类型与处理函数参数的严格匹配,但实际运行是完全安全的:
function translate(when: When): SomeCommonResultType { return translateWhenMap[when.object](when as never); }
方案优势
- 完全类型安全:没有
any类型,TypeScript会自动检查每个处理函数的参数和返回值是否符合要求 - 可维护性高:如果新增
When的子类型,映射表会直接报错,提示必须添加对应的处理函数 - 代码更简洁:相比switch分支,映射表的写法更直观,便于扩展
内容的提问来源于stack exchange,提问作者Bosse
相关产品推荐
相关产品推荐

