Search code examples
node.jstypescriptprismacasl

How to resolve the 'Argument is not assignable to parameter' error when using CASL with Prisma in TypeScript?


This is the reference which I follow to try CASL with prisma. However I got an error. This is my code:

import { user } from '@prisma/client';
import { PureAbility, AbilityBuilder, subject } from '@casl/ability';
import { createPrismaAbility, PrismaQuery, Subjects } from '@casl/prisma';

type AppAbility = PureAbility<
  [
    string,
    Subjects<{
      user: user;
    }>,
  ],
  PrismaQuery
>;
const { can, build } = new AbilityBuilder<AppAbility>(createPrismaAbility);

can('read', 'user', { id: 1 });

const ability = build();
ability.can('read', 'user');

console.log(ability.can('read', subject('user', { id: 1 }) as any)); // work
console.log(ability.can('read', subject('user', { id: 1 }))); // error here

Error:

Argument of type '{ id: number; } & ForcedSubject<"user">' is not assignable to parameter of type 'Subjects<{ user: user; }>'. Type '{ id: number; } & ForcedSubject<"user">' is not assignable to type 'Model<user, "user">'. Type '{ id: number; } & ForcedSubject<"user">' is missing the following properties from type 'user': googleId, email, password, tfaStatus, and 7 more.ts(2345)

Image: enter image description here Any solutions or tutorials would be greatly appreciated. Thank you in advance!


Solution

  • EDIT: I think this is intentional and you can't do this. You have to pass the full object. See https://github.com/stalniy/casl/issues/778

    Wrong answer:

    The { id: 1 } passed into subject needs to be type user:

    ability.can('read', subject('user', { id: 1 }) as user));

    This is why as any works as well. This is probably an oversight in the library, as it's not actually of type user.