I have a function where some of the input's properties depend on the value of one of its props. So I've defined a type as follow, and it works as expected:
enum OrganizationPermission {
UPDATE = 'organization:update',
INVITE = 'organization:invite',
}
enum WorkspacePermission {
UPDATE = 'workspace:update',
INVITE = 'workspace:invite',
}
enum OrganizationRole {
MANAGER = 'manager'
}
enum WorkspaceRole {
MANAGER = 'manager'
}
type RolePermission = {
[OrganizationPermission.UPDATE]: {
organizationRole: OrganizationRole,
},
[OrganizationPermission.INVITE]: {
organizationRole: OrganizationRole,
},
[WorkspacePermission.UPDATE]: {
workspaceRole: WorkspaceRole,
},
}
type Permissions = WorkspacePermission | OrganizationPermission;
type CheckPermissionsArgs<P extends Permissions> = {
perform: P,
sustain?: boolean,
} & (P extends keyof RolePermission ? RolePermission[P] : Record<string, never>);
function checkPermissions<P extends Permissions>(props: CheckPermissionsArgs<P>): void {
// omitted for brevity
}
The problem arises when I have to extend this props, like in the following example:
type CheckRolePermissionsArgs<P extends Permissions> = CheckPermissionsArgs<P> & {
role: string[],
}
function checkRolePermissions<P extends Permissions>({role, ...props}: CheckRolePermissionsArgs<P>): void {
// Typing error
checkPermissions(props);
}
Typescript complains that:
TS2345: Argument of type 'Pick<CheckRolePermissionsArgs
, "perform" | "sustain" | Exclude<keyof (P extends OrganizationPermission | WorkspacePermission.UPDATE ? RolePermission[P] : Record<...>), "role">>' is not assignable to parameter of type 'CheckPermissionsArgs<CheckRolePermissionsArgs
["perform"]>'. Type 'Pick<CheckRolePermissionsArgs
, "perform" | "sustain" | Exclude<keyof (P extends OrganizationPermission | WorkspacePermission.UPDATE ? RolePermission[P] : Record<...>), "role">>' is not assignable to type 'CheckRolePermissionsArgs
["perform"] extends OrganizationPermission | WorkspacePermission.UPDATE ? RolePermission[CheckRolePermissionsArgs<...>["perform"]] : Record<...>'
How can I refactor these typings to avoid casting the props
argument in the second example?