基于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
相关产品推荐
相关产品推荐

