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

无法实现条件类型:TypeScript包装函数返回类型错误求助

问题分析与修正方案

错误原因

你的泛型约束FnT extends UnknownFnT导致TypeScript无法正确区分“无回调”场景:即使不传入callback,TypeScript仍会将FnT推断为UnknownFnT的子类型(比如默认的() => void),此时PromiseRes<FnT>会被解析为Promise<ReturnType<FnT>>,而非预期的Promise<string>,返回'ok'时自然触发类型不匹配错误。

另外原代码中callback.apply(args)的用法有误:apply的第一个参数是this上下文,第二个参数才是参数数组,正确调用应为callback.apply(null, args)或直接展开参数callback(...args)。

修正方案

使用函数重载明确两种调用场景的类型,同时简化异步逻辑实现(无需手动嵌套new Promise):

type UnknownFnT = (...args: any[]) => any;

// 函数重载:定义两种调用签名
export function timePromise(ms: number): Promise<string>;
export function timePromise<FnT extends UnknownFnT>(
  ms: number,
  callback: FnT,
  ...args: Parameters<FnT>
): Promise<ReturnType<FnT>>;

// 核心实现逻辑
export async function timePromise<FnT extends UnknownFnT | undefined>(
  ms: number,
  callback?: FnT,
  ...args: FnT extends UnknownFnT ? Parameters<FnT> : []
): Promise<FnT extends UnknownFnT ? ReturnType<FnT> : string> {
  // 等待指定毫秒数
  await new Promise(resolve => setTimeout(resolve, ms));
  
  if (callback) {
    // 调用回调并返回结果(支持异步回调)
    return await callback(...args);
  }
  
  // 无回调时返回固定字符串
  return 'ok';
}

方案优势

  1. 精准类型推断:函数重载直接定义两种调用模式的类型签名,TypeScript能准确识别返回值类型:
    • 仅传ms时,返回Promise<string>
    • 传入callback和参数时,返回Promise<ReturnType<FnT>>
  2. 简化异步逻辑:利用async/await特性封装setTimeout,避免嵌套Promise的冗余写法
  3. 修正回调调用:callback(...args)更直观,且符合TypeScript的类型推断规则

测试示例

// 无回调场景:返回Promise<string>
timePromise(1000).then(res => {
  // res类型为string
  console.log(res); // 输出 'ok'
});

// 同步回调场景:返回Promise<number>
timePromise(1000, (a: number, b: number) => a + b, 1, 2).then(res => {
  // res类型为number
  console.log(res); // 输出 3
});

// 异步回调场景:返回Promise<string>
timePromise(1000, async () => {
  await new Promise(resolve => setTimeout(resolve, 500));
  return 'async result';
}).then(res => {
  // res类型为string
  console.log(res); // 输出 'async result'
});

内容的提问来源于stack exchange,提问作者Kirill Kazakov

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 06:10:42