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

基于Builder模式与动态方法选择的权限验证类型定义问题

TypeScript Builder模式权限验证函数的类型定义问题

我正在用Builder模式写一个TypeScript权限验证函数,功能运行正常,但类型定义存在问题。

使用示例:

const { can, message } = await authUser("2").can("EDIT").post("1");

我需要根据can函数传入的操作参数返回特定方法,比如传入"BLOCK"时,仅返回user(id)方法:

// 传入"BLOCK"时,只能调用user(id)方法
const { can, message } = await authUser("2").can("BLOCK").user("1");

解决思路

核心是利用TypeScript条件类型和方法重载,让can方法根据传入的操作类型,动态返回包含对应允许方法的构建器实例。

步骤1:定义操作与对应方法的映射

先明确每个操作能调用的方法集合:

// 操作类型枚举
type AuthAction = "EDIT" | "BLOCK" | "VIEW";

// 操作对应的允许方法映射
type ActionMethods<T extends AuthAction> = 
  T extends "EDIT" ? { post: (id: string) => Promise<{ can: boolean; message: string }> } :
  T extends "BLOCK" ? { user: (id: string) => Promise<{ can: boolean; message: string }> } :
  T extends "VIEW" ? { post: (id: string) => Promise<{ can: boolean; message: string }>; posts: () => Promise<{ can: boolean; message: string }> } :
  never;

步骤2:重构AuthBuilder类,引入泛型约束

让构建器类根据当前操作类型,精确暴露允许的方法:

class AuthBuilder<T extends AuthAction | undefined = undefined> {
  private userId: string;
  private action?: T;

  constructor(userId: string) {
    this.userId = userId;
  }

  // 方法重载:根据传入的action返回对应类型的构建器
  can(action: "EDIT"): AuthBuilder<"EDIT"> & ActionMethods<"EDIT">;
  can(action: "BLOCK"): AuthBuilder<"BLOCK"> & ActionMethods<"BLOCK">;
  can(action: "VIEW"): AuthBuilder<"VIEW"> & ActionMethods<"VIEW">;
  can(action: AuthAction): AuthBuilder<AuthAction> & ActionMethods<AuthAction> {
    this.action = action as T;
    // 将实例与对应方法合并,同时保证类型匹配
    return Object.assign(this, {
      post: async (id: string) => {
        // 实际权限验证逻辑,这里仅为示例
        return { can: true, message: `用户${this.userId}可以${this.action}帖子${id}` };
      },
      user: async (id: string) => {
        return { can: true, message: `用户${this.userId}可以${this.action}用户${id}` };
      },
      posts: async () => {
        return { can: true, message: `用户${this.userId}可以${this.action}所有帖子` };
      }
    }) as AuthBuilder<T> & ActionMethods<T>;
  }
}

// 初始化函数
function authUser(userId: string) {
  return new AuthBuilder(userId);
}

步骤3:验证类型约束效果

现在TypeScript会自动根据can的参数提示允许的方法,不符合操作的方法会直接报错:

// 正确:EDIT操作仅允许调用post
const editRes = await authUser("2").can("EDIT").post("1");
// 错误:BLOCK操作不能调用post(TypeScript会提示类型错误)
// const blockErr = await authUser("2").can("BLOCK").post("1");
// 正确:BLOCK操作仅允许调用user
const blockRes = await authUser("2").can("BLOCK").user("1");
// 正确:VIEW操作允许调用post和posts
const viewPostRes = await authUser("2").can("VIEW").post("1");
const viewPostsRes = await authUser("2").can("VIEW").posts();

关键说明

  • 条件类型ActionMethods明确了每个操作对应的方法集合,为类型推断提供依据
  • 方法重载让can方法返回精确的类型,确保TypeScript能准确限制可调用的方法
  • 通过Object.assign将方法挂载到构建器实例,同时保证类型与约束匹配

内容的提问来源于stack exchange,提问作者A.L. Developer

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 19:09:59