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

TypeScript如何实现带元素类型约束的数组自定义类型守卫

解决方案

核心实现

首先定义工具类型提取入参中所有可能的数组元素类型,再优化类型守卫的泛型约束即可满足你的需求,完整实现如下:

// 工具类型:提取联合类型中所有数组的元素类型
type ArrayElementOfUnion<T> = T extends Array<infer E> ? E : never;

// 优化后的数组类型守卫
const isArray = <T extends ArrayElementOfUnion<U> = ArrayElementOfUnion<U>, U>(value: U): value is T[] => {
  // 运行时校验请使用原生Array.isArray,避免类数组对象被误判
  return Array.isArray(value);
};

问题解答

  1. 不需要手动传入第二个泛型:泛型U会自动从你传入的实参推导类型,完全不需要显式声明。
  2. 自动约束泛型为数组元素类型:通过ArrayElementOfUnion工具类型,会自动提取入参所有可能的数组元素类型作为泛型T的约束,当入参类型为number[] | string[]时,T允许传入的类型只能是string | number或它们的子集。

用例验证

场景1:指定元素类型校验

const func = function(arg: string | string[] | number | number[]) {
  // 合法:string属于允许的元素类型集合,守卫会将arg收窄为string[]
  if (isArray<string>(arg)) {
    console.log(arg)
  }
  // 非法:传入boolean会直接报类型错误,符合你的预期
  // isArray<boolean>(arg)
}

场景2:不指定元素类型,仅校验是否为数组

const func = function(arg: string | string[] | number | number[]) {
  if (isArray(arg)) {
    // arg被收窄为string[] | number[]
    console.log(arg)
  } else {
    // arg被收窄为string | number
    console.log(arg)
  }
}

场景3:入参仅为数组联合类型的情况

const func = function(arg: string[] | number[]) {
  // 合法,不会报错
  if (isArray<string>(arg)) {
    // arg被收窄为string[]
    console.log(arg)
  } else {
    // arg被收窄为number[]
    console.log(arg)
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 03:48:03