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

TypeScript类型层面实现联合类型数组无重复合法组合的约束

方案1:通用工具类型+辅助函数(推荐,可自动推断无需手动传泛型)

首先定义可复用的基础工具类型,适配任意联合类型的数组去重约束:

// 基础相等判断工具类型
type Equal<X, Y> =
  (<T>() => T extends X ? 1 : 2) extends
  (<T>() => T extends Y ? 1 : 2) ? true : false;

// 判断元素是否存在于数组中
type Includes<T extends readonly unknown[], U> =
  T extends readonly [infer First, ...infer Rest]
    ? Equal<First, U> extends true
      ? true
      : Includes<Rest, U>
    : false;

// 无重复数组约束类型
type UniqueArray<T, Arr extends T[] = []> =
  // 空数组合法
  | []
  // 遍历检查每个元素是否重复
  | {
      [K in keyof Arr]: Arr[K] extends T 
        ? Includes<Arr extends [...infer Prev, unknown] ? Prev : [], Arr[K]> extends true 
          ? never 
          : Arr[K]
        : never
    }

之后针对你的EventType封装校验函数,即可直接使用,后续EventType新增可选值也无需修改其他逻辑:

type EventType = "TYPE A" | "TYPE B" | "TYPE C"; 

function defineEventTypes<T extends EventType>(arr: UniqueArray<T>) {
  return arr;
}

测试效果

// 合法场景,全部通过校验
const case1 = defineEventTypes([]);
const case2 = defineEventTypes(["TYPE A"]);
const case3 = defineEventTypes(["TYPE A", "TYPE B"]);
const case4 = defineEventTypes(["TYPE B", "TYPE C", "TYPE A"]);

// 非法场景,TS直接抛出类型错误
const errorCase1 = defineEventTypes(["TYPE A", "TYPE A"]); // 重复值报错
const errorCase2 = defineEventTypes(["TYPE A", "TYPE B", "TYPE B"]); // 重复值报错
const errorCase3 = defineEventTypes(["TYPE D"]); // 不在EventType范围内的值报错

方案2:直接标注类型(无需辅助函数)

如果不想用辅助函数,可以在标注类型时手动传入数组泛型参数:

// 合法
const arr1: UniqueArray<EventType, ["TYPE A", "TYPE B"]> = ["TYPE A", "TYPE B"];
// 报错:重复值
const arr2: UniqueArray<EventType, ["TYPE A", "TYPE A"]> = ["TYPE A", "TYPE A"];

额外说明

如果对数组元素顺序没有要求,优先使用Set<EventType>类型,原生就支持元素去重约束,不需要额外写工具类型,代码更简洁。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 06:48:04