如何在TypeScript中实现适配任意可辨识联合的类型安全Switch表达式
通用类型安全switch表达式实现方案
需求说明
假设我们在TypeScript中定义了如下可辨识联合:
type MyAction = { type: "redirect", url: string} | {type: "returnValue", value: number}
我们需要实现一个通用的switch表达式函数,满足以下要求:
- 接收可辨识联合实例,以及对应类型的处理函数映射对象,自动匹配对应的处理函数执行并返回结果
- 具备完整类型校验能力:
- 映射未覆盖所有可辨识类型时抛出错误
- 传入了不存在的类型key时抛出错误
- 处理函数中访问不属于当前类型的属性时抛出错误
示例用法如下:
let actionInstance = {type: "returnValue", value: 123} as MyAction // 输出结果为 123(value) console.log(switchExpression(actionInstance, { redirect: (action) => action.url + "(url)", returnValue: (action) => `${action.value}` + "(value)" }))
实现代码
// 辅助类型:从可辨识联合中筛选出type为指定值的子类型 type NarrowAction<T extends { type: string }, N extends T['type']> = T extends { type: N } ? T : never; // 辅助类型:生成处理函数映射的类型约束 type CasesRecord<T extends { type: string }, ReturnType> = { [K in T['type']]: (value: NarrowAction<T, K>) => ReturnType } // 通用switch表达式函数 function switchExpression<T extends { type: string }, ReturnType>( unionInstance: T, cases: CasesRecord<T, ReturnType> ): ReturnType { const matchedHandler = cases[unionInstance.type] as (value: any) => ReturnType return matchedHandler(unionInstance) }
效果验证
- 处理函数参数自动推导:
redirect对应的处理函数参数自动推导为{ type: "redirect", url: string }类型,访问value属性会直接报类型错误 - 穷尽校验:如果
cases对象中缺少任意一个MyAction的type值(比如缺了returnValue),TS会直接抛出类型错误,提示缺少对应属性 - 多余key校验:如果
cases中传入了不属于MyAction的type值(比如加了个不存在的notExistkey),TS会抛出错误提示不存在该属性
内容的提问来源于stack exchange,提问作者Noah Gilmore
相关产品推荐
相关产品推荐

