TypeScript如何按返回类型缩小调用签名联合的函数类型
问题分析
你遇到的是TypeScript针对函数联合类型的上下文类型推导限制,不属于bug,是当前版本的设计取舍:当你给变量标注Handler<TResult>联合类型时,TS无法根据你实际编写的函数的返回值、参数个数,反向推导你要匹配联合中的哪一个分支,因此参数类型推导失效,出现隐式any。
可行解决方案
方案1:使用重载辅助工厂函数(最推荐,无需手写参数类型)
通过重载匹配两种Handler类型,TS会自动根据你传入的函数签名匹配对应重载,完成类型推导:
type Callback<T> = (value: T) => void type CallbackHandler<TResult> = (event: object, cb: Callback<TResult>) => void type AsyncHandler<TResult> = (event: object) => Promise<TResult> type Handler<TResult> = CallbackHandler<TResult> | AsyncHandler<TResult> // 新增重载工厂函数 function defineHandler<TResult>(handler: AsyncHandler<TResult>): AsyncHandler<TResult> function defineHandler<TResult>(handler: CallbackHandler<TResult>): CallbackHandler<TResult> function defineHandler<TResult>(handler: Handler<TResult>) { return handler } // 使用示例 const cbHandler = defineHandler<number>((e1, cb1) => { cb1(1) // 推导正常,e1是object,cb1是Callback<number> }) cbHandler({}, () => {}) // 调用正常 const asyncHandler = defineHandler<number>(async (e2) => { return 1 // e2自动推导为object,无隐式any }) asyncHandler({}) // 调用正常,仅需1个参数
方案2:使用satisfies操作符(TS 4.9+支持)
不直接给变量标注联合类型,先完成函数推导后再用satisfies校验是否符合Handler类型约束:
const asyncHandler = async (e2: object) => { return 1 } satisfies Handler<number>
该方案需要你手动标注函数参数类型,好处是无需额外定义工具函数。
关于特性请求
当前TypeScript确实不支持基于返回值区分函数联合类型的上下文推导,如果你需要该能力,可以提交特性请求到TypeScript仓库,不过该需求属于相对边缘的场景,接受优先级可能不高。
内容的提问来源于stack exchange,提问作者Nazar
相关产品推荐
相关产品推荐

