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

TypeScript强类型工具中ReturnType<T>异常问题排查与优化

实现自动保留窄类型的ifArray工具函数

我实现了一个ifArray工具函数,功能是接收一个输入值和两个回调函数,分别处理输入为数组和非数组的情况,核心目标是尽可能保留输入的窄类型。

初始代码

export type Narrowable = string | number | boolean | symbol | object | undefined | void | null | {};
export type IsArray<T> = [T] extends [any[]] ? true : [T] extends [readonly any[]] ? true : false;
export type IfArray<T, IF, ELSE> = IsArray<T> extends true ? IF : ELSE;

export function isArray<T>(i: T) {
  return (Array.isArray(i) === true) as IsArray<T>;
}

export function ifArray<
  T extends Narrowable,
  IF extends <N extends T & readonly any[]>(arr: N) => any,
  ELSE extends <N extends Exclude<T, any[]>>(nonArr: N) => any
>(val: T, isAnArray: IF, isNotAnArray: ELSE) {
  return (
    isArray(val) ? isAnArray(val as any) : isNotAnArray(val as any)
    ) as IfArray<
      T,
      ReturnType<IF>,
      ReturnType<ELSE> // 此处类型推导异常,返回any
    >;
}

测试用例

我编写了4个测试用例验证类型推导结果:

const whatAmI0 = ifArray(
  "developer" as string,
  i => `You are a problem child with ${i.length} personalities` as const,
  i => `You are a ${i}` as const
);

const whatAmI1 = ifArray(
  "developer",
  i => `You are a problem child with ${i.length} personalities` as const,
  i => `You are a ${i}` as const
);

const whatAmI2 = ifArray(
  ["developer", "person", "husband"],
  i => `You are a problem child with ${i.length} personalities` as const,
  i => `You are a ${i}` as const
);

const whatAmI3 = ifArray(
  ["developer", "person", "husband"] as const,
  i => `You are a problem child with ${i.length} personalities` as const,
  i => `You are a ${i}` as const
);

其中whatAmI1的类型推导失败,ReturnType<ELSE>返回any类型。

已完成的修复

通过修改ELSE的泛型约束,移除其内部泛型、直接指定参数类型,修复了whatAmI1的类型推导问题:

export function ifArray<
  T extends Narrowable,
  IF extends <N extends T & readonly any[]>(arr: N) => any,
  // 修改:移除ELSE的泛型,直接指定参数类型
  ELSE extends (nonArr: Exclude<T, any[]>) => any
>(val: T, isAnArray: IF, isNotAnArray: ELSE) {
  return (
    isArray(val) ? isAnArray(val as any) : isNotAnArray(val as any)
    ) as IfArray<
      T,
      ReturnType<IF>,
      ReturnType<ELSE>
    >;
}

当前需求

目前仍需手动为回调函数的返回值添加as const才能保留窄类型,希望实现无需手动添加as const,即可自动保留回调返回值的窄类型。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 14:30:44