TypeScript中如何约束函数两个回调参数的返回类型保持一致
类型约束实现方案
不需要引入复杂的联合类型判断逻辑,使用TypeScript原生的函数重载即可满足需求,实现成本低、可读性强。
核心思路是直接在类型层面对合法的入参组合做限定,从根源上避免泛型自动推导出不符合预期的联合类型。
完整实现代码
// 原有Result类型保留 export type Result<T, E = Error> = { ok: true; val: T } | { ok: false; err: E }; // 重载签名1:两个回调均返回void function handle<T>( r: Result<T>, success: (val: T) => void, errorHandle: (err: Error) => void ): void; // 重载签名2:两个回调均返回T类型 function handle<T>( r: Result<T>, success: (val: T) => T, errorHandle: (err: Error) => T ): T; // 函数实际实现,内部逻辑不受重载签名约束 function handle<T>( r: Result<T>, success: (val: T) => T | void, errorHandle: (err: Error) => T | void ): T | void { if (r.ok) { return success(r.val); } return errorHandle(r.err); }
实现效果说明
- 类型检查会自动拦截不合法的入参:如果两个回调的返回值不统一(比如success返回T、errorHandle返回void),TS会直接抛出类型错误,不符合要求的调用无法通过编译
- 不需要编写复杂的类型工具,也不需要在运行时增加任何校验逻辑,完全依靠TS的类型系统完成约束
- 后续如果需要扩展允许的统一返回值类型,只需要对应新增重载签名即可,扩展成本极低
之前的泛型写法无法生效的核心原因是:当你给泛型R设置T | void的默认值后,TS会根据传入的两个回调的返回值自动推导出联合类型,相当于绕过了你需要的“返回值必须一致”的约束;而重载方案是直接把合法的入参组合枚举出来,从入口就排除了不合法的调用可能。
内容的提问来源于stack exchange,提问作者Alexander Haas
相关产品推荐
相关产品推荐

