You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TypeScript异步函数泛型:如何强制异步函数泛型与泛型返回类型?

实现带类型安全的异步重试工具函数(保留TypeScript类型信息)

要解决约束异步函数类型同时避免返回值双重包装的问题,关键是调整泛型约束的方式,直接将函数的返回值限定为PromiseLike<T>,让TypeScript自动推断内部值类型T,而非直接约束函数本身的泛型。

基础版实现(无参数函数)

export async function retry<T>(fn: () => PromiseLike<T>, retries: number = 1): Promise<T> {
  let attempts = 0;
  
  while (attempts < retries) {
    try {
      console.log(`Evaluating attempt #${attempts} ...`);
      return await fn();
    } catch (e) {
      console.log(`Attempt #${attempts} failed.`);
      attempts++;
      if (attempts >= retries) {
        throw e;
      }
    }
  }

  throw new Error("Retry count must be at least 1");
}

关键说明

  • 类型约束:通过fn: () => PromiseLike<T>强制传入的函数必须返回Promise或PromiseLike对象,直接排除了同步函数的可能性。
  • 返回类型处理:泛型T代表异步函数resolve后的实际值类型,await fn()会自动提取PromiseLike<T>中的T,再由async函数包装为Promise<T>,完全不会出现Promise<Promise<T>>的双重包装问题。
  • 逻辑修正:原代码最后一次失败时返回失败的Promise,这里改为直接抛出错误,让调用者能通过catch捕获最终失败,更符合重试逻辑的预期。

进阶版实现(支持带参数的函数)

如果需要重试带参数的异步函数,可以扩展泛型支持参数类型推断:

export async function retry<T, Args extends any[]>(
  fn: (...args: Args) => PromiseLike<T>,
  retries: number = 1,
  ...args: Args
): Promise<T> {
  let attempts = 0;
  
  while (attempts < retries) {
    try {
      console.log(`Evaluating attempt #${attempts} ...`);
      return await fn(...args);
    } catch (e) {
      console.log(`Attempt #${attempts} failed.`);
      attempts++;
      if (attempts >= retries) {
        throw e;
      }
    }
  }

  throw new Error("Retry count must be at least 1");
}

这个版本会自动推断待重试函数的参数类型,调用时无需手动指定,比如:

// 示例:带参数的异步函数
async function fetchData(id: number): Promise<string> {
  if (Math.random() > 0.5) throw new Error("Fetch failed");
  return `Data for ${id}`;
}

// 调用重试函数,参数类型自动匹配
retry(fetchData, 3, 123)
  .then(data => console.log(data))
  .catch(err => console.error("Final failure:", err));

内容的提问来源于stack exchange,提问作者Spencer Duball

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 19:45:31