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

TypeScript如何为依赖输入的可选数组返回值标注类型

问题

我不清楚如何正确为以下函数的返回值标注类型以消除TypeScript错误:

function simplifiedFn(
  ids: string | string[],
): typeof ids extends string[] ? number[] : number {
  const idsIsArray = Array.isArray(ids);
  const idsProvided = idsIsArray ? ids : [ids];
  
  const results = idsProvided.map((id) => parseInt(id));

  return idsIsArray ? results : results[0];
}

当前报错:

Type 'number | number[]' is not assignable to type 'number'.
Type 'number[]' is not assignable to type 'number'.

补充说明(更多上下文):
请注意这是实际函数的简化版本,因此复制parseInt(id)并非可行方案,这会带来更复杂的代码重复;也不想将这部分逻辑移至单独方法,因为需要传递大量参数,会增加当前方法的复杂度。
我认为TypeScript不应强迫用户修改最优实现来适配类型检查,这并非合理原则。
我尝试过用Array.isArray或ids instanceof Array让TypeScript更好地识别类型,但都未成功。

解决方案

方法1:函数重载(推荐)

函数重载能直接定义输入与输出的类型映射,让TypeScript准确匹配类型:

// 定义重载签名
function simplifiedFn(ids: string): number;
function simplifiedFn(ids: string[]): number[];
// 实现签名
function simplifiedFn(ids: string | string[]): number | number[] {
  const idsIsArray = Array.isArray(ids);
  const idsProvided = idsIsArray ? ids : [ids];
  
  const results = idsProvided.map((id) => parseInt(id));

  return idsIsArray ? results : results[0];
}

调用时TypeScript会自动根据参数类型推断返回值:

const singleNum = simplifiedFn("456"); // 类型为number
const numArray = simplifiedFn(["7", "8", "9"]); // 类型为number[]

方法2:泛型+类型断言

如果偏好保留条件类型的写法,可以通过类型断言让TypeScript认可分支返回值的类型:

function simplifiedFn<T extends string | string[]>(ids: T): T extends string[] ? number[] : number {
  const idsIsArray = Array.isArray(ids);
  const idsProvided = idsIsArray ? ids : [ids];
  
  const results = idsProvided.map((id) => parseInt(id));

  // 用类型断言告诉TS返回值符合条件类型的预期
  return (idsIsArray ? results : results[0]) as T extends string[] ? number[] : number;
}

这个断言是安全的,因为运行时已经通过Array.isArray确保了返回值的类型和条件类型一致。

原代码报错原因

TypeScript无法将运行时的idsIsArray检查和编译时的条件类型关联起来。条件类型是基于输入类型的静态判断,而运行时分支无法反向影响编译阶段的类型推断,因此TS会认为返回值是number | number[],不符合条件类型的预期。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 07:20:33