TypeScript如何实现带唯一值约束的枚举数组类型声明
解决方案
你原来的写法存在两个问题:一是Set<Roles>是Set实例的类型,无法直接匹配数组字面量;二是原生TS没有直接校验数组元素唯一性的内置类型,需要自己实现工具类型配合泛型推导实现。
第一步:实现唯一性校验工具类型
// 判断类型T是否在数组U中存在 type Includes<T, U extends any[]> = U extends [infer First, ...infer Rest] ? T extends First ? true : Includes<T, Rest> : false; // 校验数组元素是否唯一 type IsUnique<T extends any[]> = T extends [infer First, ...infer Rest] ? Includes<First, Rest> extends true ? false : IsUnique<Rest> : true;
第二步:定义业务枚举和泛型接口
export enum Roles { Role1 = 'Role1', Role2 = 'Role2', Role3 = 'Role3', } // 泛型接口,接收permissions对应的数组类型做校验 export interface SomeInterface<T extends Roles[]> { // 元素唯一则返回原数组类型,否则返回never触发类型报错 permissions: IsUnique<T> extends true ? T : never; }
第三步:使用工厂函数实现自动校验(推荐)
手动声明泛型参数成本较高,用工厂函数可以自动推导数组类型,重复时直接抛出警告:
// 工厂函数定义 function createSomeConfig<T extends Roles[]>(config: SomeInterface<T>) { // 若需要运行时校验,可增加如下逻辑 // if (new Set(config.permissions).size !== config.permissions.length) { // throw new Error('permissions存在重复角色') // } return config; } // 正确示例:无重复,无报错 const validConfig = createSomeConfig({ permissions: [Roles.Role1, Roles.Role2] }); // 错误示例:有重复,TS直接抛出类型错误 const invalidConfig = createSomeConfig({ permissions: [Roles.Role1, Roles.Role1] // 此处会飘红提示类型不匹配 });
内容的提问来源于stack exchange,提问作者Святослав Марюха
相关产品推荐
相关产品推荐

