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

TypeScript条件返回类型函数编译报错问题求助

TypeScript条件返回类型报错问题解决

问题描述

尝试为函数实现条件返回类型:根据传入options参数中includeRelated的值,返回string或[string, string[]]类型,但编译器在返回语句处报错。

报错代码

function fetchFromDB() {
  return 'Apple';
}

function fetchRelatedFromDB() {
  return ['Banana', 'Cherry'];
}

type Options = {
  includeRelated?: boolean;
};

type ConditionalReturn<T extends Options> = T extends {
  includeRelated: true;
}
  ? [string, string[]]
  : string;

export function find<T extends Options>(
  options: T
): ConditionalReturn<T> {
  const fruit = fetchFromDB();

  if (options.includeRelated) {
    const related = fetchRelatedFromDB();
    return [fruit, related]; // 第26行报错
  }

  return fruit; // 第29行报错
}

const stringResult = find({});

const tupleResult = find({ includeRelated: true });

问题原因

TypeScript无法在函数内部通过if (options.includeRelated)的类型收窄,关联到泛型T的条件判断逻辑。泛型T的具体类型是在函数调用时确定的,函数内部无法直接证明返回值完全匹配ConditionalReturn<T>的约束。

解决方案

方案一:类型断言

直接为返回值添加类型断言,明确告知编译器返回值符合条件类型:

export function find<T extends Options>(
  options: T
): ConditionalReturn<T> {
  const fruit = fetchFromDB();

  if (options.includeRelated) {
    const related = fetchRelatedFromDB();
    return [fruit, related] as ConditionalReturn<T>;
  }

  return fruit as ConditionalReturn<T>;
}

方案二:函数重载

使用函数重载替代泛型条件类型,逻辑更直观,编译器能更好地推断类型:

// 重载签名
export function find(options: { includeRelated: true }): [string, string[]];
export function find(options?: { includeRelated?: false }): string;

// 实现签名
export function find(options: Options = {}) {
  const fruit = fetchFromDB();

  if (options.includeRelated) {
    const related = fetchRelatedFromDB();
    return [fruit, related];
  }

  return fruit;
}

两种方案都能解决报错问题,且调用处的类型推断正常:

  • const stringResult = find({}) 类型为string
  • const tupleResult = find({ includeRelated: true }) 类型为[string, string[]]

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 01:08:13