#995·casl

Missing type-checking in classes with protected constructor

Author: yodosanCreated Dec 3, 2024Updated Jan 12, 2025
Labelsbug

Describe the bug Hello, I'm trying to set up CASL with NestJS and get full TypeScript support defining each ability (actions, subjects, fields, conditions) but something is missing. My classes have the constructor protected, which CASL doesn't seem to like very much; however, I think I found an acceptable trade-off (if somewhat verbose).

This is what I've done so far:

bash
class UserEntity {
  protected constructor(
    readonly id: string,
    readonly name: string,
    readonly createdBy: Date
  ) {}

  static create(id: string, name: string) {
    return new UserEntity(id, name, new Date())
  }
}

type Actions = 'create' | 'read' | 'update' | 'delete'

type User = UserEntity & TaggedInterface<'UserEntity'>
type Subjects = InferSubjects<User> | 'all'
type AppAbility = PureAbility<[Actions, Subjects]>

@Injectable()
export class CASLAbilityFactory {
  createForUser() {
    const { can, build } = new AbilityBuilder<AppAbility>(PureAbility)

    can<User>('create', 'UserEntity')

    return build()
  }
}

Now, the action, the subject, and the fields are correctly checked, but for some reason, it can be done for the properties; as we can see there is no type-checking:

Screenshot 2024-12-03 alle 17 29 16

Is CASL doing something wrong or is it me?

CASL Version

@casl/ability: 6.7.2

Environment: TypeScript: 5.6.3 NodeJS: 22