TypeScript中如何转换函数签名为异步并保留泛型类型?
解决TypeScript泛型函数Promisify时保留泛型的问题
要解决泛型函数转为异步时丢失泛型类型的问题,关键是在类型转换中保留原函数的泛型参数结构,而不是直接提取参数和返回值(后者会将未实例化的泛型解析为unknown)。
正确的Promisify类型定义
type Promisify<F> = // 匹配带泛型参数的函数 F extends <T>(...args: infer Args) => infer R ? R extends Promise<any> ? F // 如果已经是异步函数,直接返回原类型 : <T>(...args: Args) => Promise<Awaited<R>> // 同步泛型函数转为异步,保留泛型 // 匹配普通非泛型函数 : F extends (...args: infer Args) => infer R ? R extends Promise<any> ? F : (...args: Args) => Promise<Awaited<R>> : never;
验证效果
测试你的示例代码:
const syncIdentity = <T>(o: T) => o; // 原类型:<T>(o: T) => T type PromisifiedSyncIdentity = Promisify<typeof syncIdentity>; // 结果:<T>(o: T) => Promise<T> ✅ const asyncIdentity = async <T>(o: T) => o; // 原类型:<T>(o: T) => Promise<T> type PromisifiedAsyncIdentity = Promisify<typeof asyncIdentity>; // 结果:<T>(o: T) => Promise<T> ✅
再测试普通非泛型函数:
const syncAdd = (a: number, b: number) => a + b; type PromisifiedAdd = Promisify<typeof syncAdd>; // 结果:(a: number, b: number) => Promise<number> ✅
为什么之前的尝试失败
- 第一次尝试直接使用
Parameters<F>和ReturnType<F>,对于泛型函数,TypeScript无法保留未实例化的泛型参数,会自动将其解析为unknown。 - 第二次尝试对同步泛型函数仍使用了
Parameters<F>和ReturnType<F>,所以依然丢失泛型;仅异步函数因为直接返回原类型,才保留了泛型。
版本兼容性
这个方案在你使用的TypeScript 4.7.3版本中完全可行,条件类型对泛型函数的匹配逻辑在4.x版本已经稳定支持。
内容的提问来源于stack exchange,提问作者Alexandre LEGOUT
相关产品推荐
相关产品推荐

