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

TypeScript如何确保枚举值数组仅包含唯一的枚举成员?

TypeScript 枚举数组的合法值与唯一性校验方案

一、合法值的正确类型限定

你当前用(keyof typeof StringsVals)[]的写法存在隐患:因为数字枚举会生成反向映射(比如StringsVals[0] = 'aaa'同时StringsVals['aaa'] = 0),keyof typeof StringsVals会同时包含枚举的字符串键('aaa'等)和数字值对应的字符串('0'、'1'等),导致数组可以混入非法的数字字符串。

要严格限定数组元素为枚举的合法字符串值,直接使用枚举的成员类型即可:

enum StringsVals {
  'aaa',
  'bbb',
  'ccc'
}

// 正确限定:仅允许枚举的合法字符串成员
const x: StringsVals[] = ['aaa', 'bbb']; // 合法
const z: StringsVals[] = ['ddd']; // TypeScript直接报错

二、元素唯一性的校验方案

TypeScript的类型系统不支持在编译阶段直接校验数组元素的唯一性——因为类型系统基于结构而非具体值,无法追踪数组内的重复项。但可以通过两种方式实现需求:

1. 联合类型元组(适用于成员较少的枚举)

如果枚举成员数量不多,可以手动定义枚举成员联合类型的元组,利用Exclude工具类型排除已使用的成员:

// 提取枚举的字符串成员联合类型
type StringsValsUnion = 'aaa' | 'bbb' | 'ccc';

// 定义支持不同长度的唯一元素元组类型
type UniqueEnumTuple<T> = 
  | []
  | [T]
  | [T, Exclude<T, T[0]>]
  | [T, Exclude<T, T[0]>, Exclude<T, T[0] | T[1]>];

const validX: UniqueEnumTuple<StringsValsUnion> = ['aaa', 'bbb']; // 合法
const invalidY: UniqueEnumTuple<StringsValsUnion> = ['aaa', 'aaa']; // TypeScript报错

缺点是枚举成员增加时,需要手动扩展元组的长度定义,灵活性差。

2. 运行时校验+类型断言(通用方案)

更实用的方式是编写运行时校验函数,同时通过类型断言让TypeScript认可校验后的数组类型:

enum StringsVals {
  'aaa',
  'bbb',
  'ccc'
}

// 提前缓存枚举的合法字符串值
const validEnumValues = new Set(
  Object.values(StringsVals).filter(val => typeof val === 'string')
);

// 断言函数:校验数组元素的合法性与唯一性
function assertUniqueEnumArray(arr: unknown[]): asserts arr is StringsVals[] {
  const seen = new Set();
  for (const item of arr) {
    if (typeof item !== 'string' || !validEnumValues.has(item)) {
      throw new Error(`非法枚举值:${item}`);
    }
    if (seen.has(item)) {
      throw new Error(`重复枚举值:${item}`);
    }
    seen.add(item);
  }
}

// 使用示例
const x = ['aaa', 'bbb'];
assertUniqueEnumArray(x); // 校验通过,无报错

const y = ['aaa', 'aaa'];
assertUniqueEnumArray(y); // 运行时抛出"重复枚举值"错误

这种方案兼顾了编译时的类型检查和运行时的唯一性校验,适合绝大多数场景。

总结

  • 合法值校验:直接用StringsVals[]类型替代(keyof typeof StringsVals)[],避免反向映射带来的非法值问题。
  • 唯一性校验:TypeScript编译阶段无法直接实现,推荐采用运行时校验函数+类型断言的方案,小枚举场景可尝试联合类型元组。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 10:47:57