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

如何避免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" }); // 无重复

方案说明

  1. 类型层面约束

    • ExtractRole:统一解析参数的角色值,不管是直接传UserRole字符串还是传{role: UserRole}对象,都能得到对应的角色字符串。
    • HasDuplicates:通过递归遍历数组元素,检查是否存在任意两个元素的角色值重复,存在则返回true。
    • UniqueRoleParams:利用条件类型,当参数数组存在重复角色时,将参数类型置为never,触发TypeScript的编译报错,在开发阶段就拦截问题。
  2. 运行时校验
    即使有静态类型检查,依然需要运行时校验——比如从后端接口动态获取参数、或者通过any类型绕过类型检查的场景,此时通过Set去重后对比长度,判断是否存在重复角色,有则抛出错误终止执行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 17:55:10