Typescript error

default discord avatar
ndeji9 months ago
6

I am trying to restrict access to the admin panel to just

superAdmins

and

admins

both of which are roles on the user collection.



problem: I get the typescript error when i hover over

users.access.admin

access control function:


 Type 'Access' is not assignable to type '(args?: any) => boolean | Promise<boolean>'.
  Type 'AccessResult | Promise<AccessResult>' is not assignable to type 'boolean | Promise<boolean>'.
    Type 'Where' is not assignable to type 'boolean | Promise<boolean>'.
      Type 'Where' is missing the following properties from type 'Promise<boolean>': then, catch, finally, [Symbol.toStringTag]ts(2322)
types.d.ts(311, 9): The expected type comes from property 'admin' which is declared here on type '{ create?: Access; read?: Access; readVersions?: Access; update?: Access; delete?: Access; admin?: (args?: any) => boolean | Promise<boolean>; unlock?: Access; }'


Here is my Users collectio:


import { CollectionConfig } from "payload/types";
import isSuperAdmin from "../access/isSuperAdmin";
import isAdmin from "../access/isSuperAdmin";
import isSuperAdminOrAdmin from "../access/isSuperAdminOrAdmin";

const Users: CollectionConfig = {
  slug: "users",
  auth: {
    cookies: {
      // disabe "secure" property when in development mode, otherwise no cookies will be set
      // secure: process.env.PAYLOAD_ENV !== "development",
      sameSite: process.env.PAYLOAD_ENV === "testing" ? "none" : "lax",
    },
  },
  access: {
    create: isAdmin,
    admin: isSuperAdminOrAdmin,
  },
  admin: {
    useAsTitle: "email",
  },
  fields: [
    {
      name: "fullName",
      label: "Full Name",
      type: "text",
      // required: true,
    },
    {
      name: "phoneNumber",
      type: "number",
      label: "Phone Number",
      // required: true,
      unique: true,
    },
    {
      name: "transactionPin",
      type: "number",
      label: "Transaction Pin",
      // hidden: true, #uncomment this to make Transaction Pin to be visible in the admin UI
      // required: true,
      unique: true,
    },
    {
      name: "roles",
      type: "select",
      hasMany: true,
      saveToJWT: true,
      options: [
        {
          label: "Super Admin",
          value: "superAdmin",
        },
        {
          label: "Admin",
          value: "admin",
        },
        {
          label: "Api User",
          value: "apiUser",
        },
        {
          label: "Normal user",
          value: "normalUser",
        },
      ],
    },
  ],
};

export default Users;


isSuperAdminOrAdmin

function:


import { Access } from "payload/types";
import { User } from "../payload-types";

const isSuperAdminOrAdmin: Access<any, User> = async ({ req: { user } }) => {
  const isSuperAdmin = user?.roles?.includes("superAdmin");
  const isAdmin = user?.roles?.includes("admin");

  return Boolean(isSuperAdmin || isAdmin);
};

export default isSuperAdminOrAdmin;
  • default discord avatar
    dr_mint9 months ago

    Hi! Pretty much what the error says: all the access controls expect an

    Access

    type function (which returns a boolean OR a Where), but the admin one expect a function that returns a boolean. Because

    isSuperAdminOrAdmin

    is typed as

    Access

    , it means that it could, in theory, return either a boolean or a Where. Now looking at the function, it is clear it will only ever return a boolean, but Typescript doesn't know that.



    If you are using Typescript >= 4.9, you can use the

    satisfies

    keyword to let Typescript infer a more precise type for the function (in which case it will consider it a function that return a boolean), while still

    satisfying

    the requirements of being an

    Access

    function. It would look like this:



    const isSuperAdminOrAdmin = (({ req: { user } }) => {
      const isSuperAdmin = user?.roles?.includes("superAdmin");
      const isAdmin = user?.roles?.includes("admin");
    
      return Boolean(isSuperAdmin || isAdmin);
    }) satisfies Access<any, User>;

    I also removed the async as there wasn't any await inside the function

  • default discord avatar
    ndeji9 months ago

    @dr_mint I can't thank you enough, I am really grateful.


    The error has been resolved.



    If you don't mind, please where/how can I check the return type of Access function.

  • default discord avatar
    dr_mint9 months ago

    Glad it helped. If you are using VSCode, you should be able to hold the Ctrl key and left click on a variable/class/type. It will bring you to its definition. Alternatively, you can right-click on a type/variable/class/function and click on "Go to Definition" or "Go to Type Definition"

  • default discord avatar
    ndeji9 months ago

    It worked.


    However, I couldn't see a

    Where

    return type anywhere, perhaps I may be missing something.



    Screenshot_48.png
  • default discord avatar
    dr_mint9 months ago

    The Where is part of the return type of the function. You need to do the same Ctrl+click maneuver on

    AccessResult
  • default discord avatar
    ndeji9 months ago

    Got it now. Thank you once again.

Star on GitHub

Star

Chat on Discord

Discord

online

Can't find what you're looking for?

Get help straight from the Payload team with an Enterprise License.