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

TypeScript条件返回类型函数报错:返回值类型不匹配求助

解决TypeScript条件返回类型不匹配问题

问题分析

你当前的条件类型BotLotteryPrizeOrLot<T>逻辑上成立,但TypeScript无法在函数内部跟踪wonItem的类型与泛型T的关联——forEach循环会抹平类型细节,TS只能识别wonItem为BotLotteryPrize | Lot,无法确认它恰好匹配BotLotteryPrizeOrLot<T>的约束,因此抛出类型不匹配错误。

解决方案一:调整泛型约束,简化类型推断

直接将泛型约束在单个奖品类型上,让TS自动根据输入数组的类型推导返回值类型,无需额外条件类型:

function raffleDrawWithDistribution<T extends BotLotteryPrize | Lot>(
  items: T[],
): T {
  const randomInt = this.generateRandomInt();

  const sumOfProbabilities = items.reduce(
    (acc, currentItem) => acc + currentItem.probabilityToWin,
    0,
  );

  if (sumOfProbabilities !== 1) {
    items.forEach((item) => {
      item.probabilityToWin = item.probabilityToWin / sumOfProbabilities;
    });
  }

  const probabilities = items.reduce(
    (acc, currentLot, idx) => {
      const nextProbability = acc[idx] + currentLot.probabilityToWin;
      return [...acc, nextProbability];
    },
    [0],
  );

  let wonItem: T | null = null;

  items.forEach((item, idx) => {
    if (randomInt > probabilities[idx] && randomInt <= probabilities[idx + 1]) {
      wonItem = item;
    }
  });

  // 处理空数组的边界情况,确保运行时安全
  if (!wonItem) {
    throw new Error("No items provided for raffle draw");
  }

  return wonItem;
}

优势

  • 泛型T直接绑定输入数组的元素类型,TS能清晰推断返回值为T,避免类型歧义。
  • 内部wonItem的类型与输入元素完全匹配,赋值时不会出现类型冲突。
  • 新增空数组判断,同时保证运行时安全与类型正确性。

解决方案二:用函数重载严格约束输入输出

如果需要严格禁止传入混合BotLotteryPrize和Lot的数组,可以通过函数重载明确合法的输入输出组合:

// 重载声明:明确两种合法的输入输出配对
function raffleDrawWithDistribution(items: BotLotteryPrize[]): BotLotteryPrize;
function raffleDrawWithDistribution(items: Lot[]): Lot;

// 通用实现
function raffleDrawWithDistribution(
  items: (BotLotteryPrize | Lot)[]
): BotLotteryPrize | Lot {
  const randomInt = this.generateRandomInt();

  const sumOfProbabilities = items.reduce(
    (acc, currentItem) => acc + currentItem.probabilityToWin,
    0,
  );

  if (sumOfProbabilities !== 1) {
    items.forEach((item) => {
      item.probabilityToWin = item.probabilityToWin / sumOfProbabilities;
    });
  }

  const probabilities = items.reduce(
    (acc, currentLot, idx) => {
      const nextProbability = acc[idx] + currentLot.probabilityToWin;
      return [...acc, nextProbability];
    },
    [0],
  );

  let wonItem: BotLotteryPrize | Lot | null = null;

  items.forEach((item, idx) => {
    if (randomInt > probabilities[idx] && randomInt <= probabilities[idx + 1]) {
      wonItem = item;
    }
  });

  if (!wonItem) {
    throw new Error("No items provided for raffle draw");
  }

  return wonItem;
}

优势

  • 明确禁止混合类型数组的输入,编译阶段就会拦截非法调用。
  • 调用方无需手动指定泛型,TS会根据输入自动匹配对应的重载,返回正确类型。

内容的提问来源于stack exchange,提问作者Thibault Walterspieler

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 14:20:22