I have an object which contains roles which are an array of rights which they grant e.g.
const allRoles = {
user: [
'right1'
],
admin: [
'right1',
'right2'
],
} as const
If I wanted to get the types for user rights and admin rights I could do:
type userRights = Array<typeof allRoles.user[number]>
type adminRights = Array<typeof allRoles.admin[number]>
And to get the types for both I could do:
type RoleRights = userRights | adminRights
I don't need individual user rights or admin rights. Is there a way I can represent all of the available rights in on type declaration?
Similar to how if I wanted to create an array of all rights I could do:
const roleRights = new Map(Object.entries(allRoles))
CodePudding user response:
Assuming you want to infer your types using as const
from the allRoles
object, you could do the following:
const allRoles = {
user: [
'right1'
],
admin: [
'right1',
'right2'
],
} as const
type RolesMap = typeof allRoles;
/*
{
readonly user: readonly ["right1"];
readonly admin: readonly ["right1", "right2"];
}
*/
type UserRoles = RolesMap['user']; // readonly ["right1"]
type AdminRoles = RolesMap['admin']; // readonly ["right1", "right2"]
type AllRoles = UserRoles | AdminRoles; // readonly ["right1"] | readonly ["right1", "right2"]
Note: This will make fixed types out of ['right1']
and ['right1', 'right2']
, you will notice this is therefore not automatically collapsed into something like ('right1' | 'right2')[]
which I imagine is what you are after.
However if you already know all of the rights in advance, which I imagine you likely do, architecturally it may make more sense to type the system the other way around, starting from the rights and building up to the map, e.g.
enum RightsEnum {
right1 = 'right1',
right2 = 'right2',
right3 = 'right3',
...
}
enum RolesEnum {
user = 'user',
admin = 'admin'
}
// explicit
interface RolesMap {
[RolesEnum.user]: [RightsEnum.right1],
[RolesEnum.admin]: [RightsEnum.right1, RightsEnum.right2]
}
// generic
type RolesMap = Record<RolesEnum, RightsEnum>;
const allRoles: RolesMap = {
user: [
'right1'
],
admin: [
'right1',
'right2'
],
}
Your "all rights" type would therefore just be RightsEnum
CodePudding user response:
type userRight = typeof allRoles.user[number]
type adminRight = typeof allRoles.admin[number]
type userRights = userRight[]
type adminRights = adminRight[]
type RoleRights = (userRight | adminRight)[]