NestJS中CASL权限配置报错:can方法重载不匹配
问题
在NestJS项目中实现CASL权限认证时,执行can(Action.Update, selectTeamSchema, { createdById: user.id })代码出现类型错误,报错提示can方法的两个重载均不匹配,Action.Update类型无法赋值给never[]类型。
报错信息
No overload matches this call. Overload 1 of 2, '(action: never[], subject: never[], fields?: string | string[], conditions?: MongoQuery<never>): RuleBuilder<MongoAbility<PossibleAbilities, Conditions>>', gave the following error. Argument of type 'import("/src/ability/ability.factory").Action' is not assignable to parameter of type 'never[]'. Overload 2 of 2, '(action: never[], subject: never[], conditions?: MongoQuery<never>): RuleBuilder<MongoAbility<PossibleAbilities, Conditions>>', gave the following error. Argument of type 'import("src/ability/ability.factory").Action' is not assignable to parameter of type 'never[]'.ts(2769) (enum member) Action.Update = "update"
相关代码
type Subjects = InferSubjects<SelectUserType | SelectTeamType>; type PossibleAbilities = [Action, Subjects]; export type Conditions = MongoQuery; export type AppAbility = MongoAbility<PossibleAbilities, Conditions>; export enum Action { Manage = 'manage', Create = 'create', Read = 'read', Update = 'update', Delete = 'delete', } @Injectable() export class AbilityFactory { userInTeamAbility(user: SelectUserType) { const { can, cannot, build } = new AbilityBuilder( createMongoAbility<PossibleAbilities, Conditions>, ); can(Action.Update, selectTeamSchema, { createdById: user.id }); return build({ detectSubjectType: (item) => item.constructor as ExtractSubjectType<Subjects>, }); } }
错误原因与解决方案
核心原因
InferSubjects对Zod对象推导失效:CASL的InferSubjects默认基于类/构造函数推导类型,但SelectUserType和SelectTeamType是Zod对象,无法被正确识别,导致Subjects被推导为never,进而让PossibleAbilities的类型异常,最终使can方法的参数类型被错误推断为never[]。- subject参数类型不匹配:
can方法的subject参数需要对应Subjects类型的构造函数或标识,但你传入的是Zod schema对象,类型不匹配进一步触发了类型错误。
修复步骤
明确定义Subjects类型
放弃依赖InferSubjects,直接为Zod对应的业务实体定义字符串标识:type Subjects = 'User' | 'Team';调整PossibleAbilities类型
确保能力类型的定义清晰准确:type PossibleAbilities = [Action, Subjects];修正can方法的调用
传入字符串形式的subject标识,而非Zod schema对象:can(Action.Update, 'Team', { createdById: user.id });完善detectSubjectType逻辑
如果需要处理实体实例的类型检测,调整逻辑以识别Zod解析后的对象(假设解析后的对象带有标识字段):detectSubjectType: (item) => { return (item as { modelName?: Subjects }).modelName ?? 'Team'; }
内容的提问来源于stack exchange,提问作者rafaelHTML
相关产品推荐
相关产品推荐

