如何避免process函数参数中UserRole类型的重复项?
实现参数中UserRole值的去重校验
要实现process函数参数中角色值的去重校验,需要同时从TypeScript静态类型检查和运行时校验两个层面入手,既在编译阶段拦截重复参数,也在运行时处理动态传入的场景。
完整实现代码
type UserRole = "admin" | "seller" | "customer"; type UserRoleInOject = { role: UserRole; }; // 提取单个参数对应的角色值,统一字符串和对象两种格式 type ExtractRole<T> = T extends UserRole ? T : T extends UserRoleInOject ? T['role'] : never; // 递归检查数组中是否存在重复的角色 type HasDuplicates<T extends readonly any[]> = T extends [infer First, ...infer Rest] ? ExtractRole<First> extends ExtractRole<Rest[number]> ? true : HasDuplicates<Rest> : false; // 约束参数数组:只有无重复角色的数组才合法,否则类型为never触发报错 type UniqueRoleParams<T extends (UserRole | UserRoleInOject)[]> = HasDuplicates<T> extends false ? T : never; function process<T extends (UserRole | UserRoleInOject)[]>( ...userTypes: UniqueRoleParams<T> ): void { // 运行时校验:处理动态传入的参数(绕过类型检查的场景) const roles = userTypes.map(item => typeof item === 'string' ? item : item.role); const uniqueRoleSet = new Set(roles); if (uniqueRoleSet.size !== roles.length) { throw new Error('参数中存在重复的角色'); } // 后续业务逻辑 console.log('处理无重复角色的参数:', roles); }
效果验证
以下调用会触发类型编译报错(符合预期,拦截重复参数):
process("admin", { role: "seller" }, { role: "admin" }); // 重复admin process({ role: "admin" }, { role: "admin" }, "customer"); // 重复admin
以下调用可正常执行:
process("admin", "seller", "customer"); // 无重复 process({ role: "admin" }, { role: "seller" }, { role: "customer" }); // 无重复
方案说明
类型层面约束
ExtractRole:统一解析参数的角色值,不管是直接传UserRole字符串还是传{role: UserRole}对象,都能得到对应的角色字符串。HasDuplicates:通过递归遍历数组元素,检查是否存在任意两个元素的角色值重复,存在则返回true。UniqueRoleParams:利用条件类型,当参数数组存在重复角色时,将参数类型置为never,触发TypeScript的编译报错,在开发阶段就拦截问题。
运行时校验
即使有静态类型检查,依然需要运行时校验——比如从后端接口动态获取参数、或者通过any类型绕过类型检查的场景,此时通过Set去重后对比长度,判断是否存在重复角色,有则抛出错误终止执行。
内容的提问来源于stack exchange,提问作者Maxent
相关产品推荐
相关产品推荐

