TypeScript中如何实现返回不同签名函数的正确类型推导?
解决方案
方法一:用类型断言修复现有泛型实现
TypeScript没法在switch分支里自动细化泛型R的具体类型,我们可以用类型断言明确告诉编译器当前分支的返回值符合泛型对应的类型。同时通过穷尽性检查替代多余的默认返回,确保覆盖所有Reason分支:
type Reason = 'create' | 'delete'; type DispatchedFunction<T extends Reason> = T extends 'create' ? typeof createInternal : typeof deleteInternal; function createInternal(name: string) { console.log(name); } function deleteInternal(code: number) { console.log(code); } function dispatch<R extends Reason>(reason: R): DispatchedFunction<R> { switch(reason) { case 'create': return createInternal as DispatchedFunction<R>; case 'delete': return deleteInternal as DispatchedFunction<R>; } // 穷尽性检查:如果新增了Reason类型但没处理,这里会报错 const _exhaustiveCheck: never = reason; throw new Error(`Unexpected reason: ${_exhaustiveCheck}`); } // 调用正常 dispatch('create')('123'); dispatch('delete')(123);
方法二:对象映射实现(更简洁推荐)
通过对象字面量建立reason和对应函数的映射,TypeScript会自动推导类型关联,不需要手动编写条件分支,扩展性更强:
// 建立reason到处理函数的映射 const dispatchMap = { create: (name: string) => { console.log(name); }, delete: (code: number) => { console.log(code); } } // 从映射对象自动推导Reason类型 type Reason = keyof typeof dispatchMap; // 定义dispatch函数,泛型自动关联reason与返回函数的类型 function dispatch<R extends Reason>(reason: R): typeof dispatchMap[R] { return dispatchMap[reason]; } // 调用正常 dispatch('create')('123'); dispatch('delete')(123);
两种方法对比
- 方法一适合需要保留switch分支逻辑的场景,通过类型断言解决泛型细化问题,同时保留穷尽性检查避免遗漏分支。
- 方法二更简洁,类型推导完全自动化,新增操作时只需修改映射对象,维护成本更低,也减少了手动编写switch的出错概率。
内容的提问来源于stack exchange,提问作者KorbenDose
相关产品推荐
相关产品推荐

