TypeScript:使用.call调用重试函数时如何推断返回类型?
如何让
Function.prototype.call正确推断泛型函数的返回类型 问题原因
你的代码中response被推断为unknown,主要有两个核心原因:
Parent类的token属性未明确标注类型,导致bar函数的返回类型推断不够清晰;- 当通过
Function.prototype.call调用带有自定义泛型的函数(如retryOnce)时,TypeScript的自动泛型推断可能因嵌套逻辑失效,无法识别fn的返回类型。
解决方案
1. 明确类属性类型,消除隐式any
先给Parent类的token加上类型标注,让TypeScript能准确推断bar的返回类型:
class Parent { token: number; // 明确标注属性类型 constructor(token: number){ this.token = token; } async someMethod(){ const bar = () => someTypedFunction("variable", this.token); // ... } }
2. 手动指定泛型参数
在调用retryOnce时,直接指定其泛型参数R,强制TypeScript识别返回类型:
async someMethod(){ const bar = () => someTypedFunction("variable", this.token); const response = await retryOnce<Promise<string>>.call(this, bar); return response; // 此时response自动推断为string }
3. 调整retryOnce的调用方式(更优雅)
如果不想依赖call的泛型推断逻辑,可以修改retryOnce的定义,将this作为显式参数传入,让类型推断更直接:
// 修改retryOnce,用ctx代替this隐式参数 async function retryOnce<R>(ctx: any, fn: () => R): Promise<R> { let isRetry = false; const execute = async () => { try{ return await fn(); }catch(error: any){ if(!isRetry){ isRetry = true; ctx.token = getNewToken(); return execute(); }else{ throw Error(); } } } return execute(); } // 在Parent类中调用 async someMethod(){ const bar = () => someTypedFunction("variable", this.token); const response = await retryOnce(this, bar); return response; // 自动推断为string }
关于Function.prototype.call的泛型支持
Function.prototype.call本身是支持泛型的,其官方类型定义如下:
call<T, A extends any[], R>(this: (this: T, ...args: A) => R, thisArg: T, ...args: A): R;
但当调用的函数自身带有泛型参数时,TypeScript的自动推断逻辑可能无法同时解析两层泛型关系,此时手动指定泛型参数或调整代码结构是更可靠的选择。
不要随意使用any绕过类型检查,这会丧失TypeScript的类型安全优势,优先通过明确类型标注或调整代码结构实现正确的类型推断。
内容的提问来源于stack exchange,提问作者CoolHandClay
相关产品推荐
相关产品推荐

