如何在TypeScript中定义无重复元素的字符串组合数组类型
在TypeScript中定义无重复非空字符串组合数组类型
针对你需要限制数组为指定字符串的无重复非空组合(对应数学中的组合概念)的需求,普通的联合类型数组(如CASE[])无法限制重复元素,下面提供两种可行方案:
方案1:精确生成所有非空无重复组合(适合元素数量较少场景)
通过递归类型生成所有符合要求的元组组合,自动覆盖单元素、多元素的所有可能(包括不同顺序的合法组合):
// 定义基础角色类型(替换为你的业务类型) type Role = 'Operator' | 'Manufacturer' | 'Distributor'; // 递归生成所有非空无重复子集的元组类型 type NonEmptySubset<T extends string> = T extends infer U ? U[] extends (infer V)[] ? V extends U ? [V] | [V, ...NonEmptySubset<Exclude<U, V>>] : never : never : never; // 最终的用户角色组合类型 type UserRoles = NonEmptySubset<Role>;
测试示例
// 合法赋值(不会报错) const singleRole: UserRoles = ['Operator']; const twoRoles: UserRoles = ['Manufacturer', 'Distributor']; const allRoles: UserRoles = ['Distributor', 'Operator', 'Manufacturer']; // 顺序不影响合法性 // 非法赋值(TypeScript会报错) const duplicateRole: UserRoles = ['Operator', 'Operator']; // 重复元素 const emptyRole: UserRoles = []; // 空数组 const invalidRole: UserRoles = ['Unknown']; // 不属于指定类型
方案2:通用型唯一元素数组校验(适合任意元素数量)
通过条件类型直接校验数组元素的唯一性、非空性和类型合法性,无需提前枚举所有组合:
type Role = 'Operator' | 'Manufacturer' | 'Distributor'; // 限制数组为非空、元素唯一且属于指定类型 type UniqueArray<T, U extends T[] = []> = U extends [infer First, ...infer Rest] ? Rest extends T[] ? First extends Rest[number] ? never : U : never : U extends T[] ? U extends [] ? never : U : never; type UserRoles = UniqueArray<Role>;
测试效果
和方案1一致,非法的重复、空数组、未知类型都会被TypeScript自动拦截。
原代码问题说明
你之前的CASE[]类型仅约束了数组元素属于CASE联合类型,但没有限制重复元素和非空,所以无法拦截["A","A"]这类非法值。上述两种方案通过TypeScript的条件类型和递归特性,补全了这两个约束。
内容的提问来源于stack exchange,提问作者Minh
相关产品推荐
相关产品推荐

