1

I have a string enum defined as follows:

export enum UserRole {
  SHOP_DESIGNER = 'DG_PF00-CorpID-Designa_Shop-Designers',
  SHOP_EMPLOYEE = 'DG_PF00-CorpID-Designa_Shop-Employees',
  LOGISTICS_TEAM = 'DG_PF00-CorpID-Designa_Logistics',
}

I want to create a type-safe mapping from a an enum string value to its enum type:

const USER_ROLE_NAMES<string, UserRole> = ....

So I can parse an arbitrary value by querying the map:

let role: UserRole

// role = SHOP_DESIGNER 
role = USER_ROLE_NAMES.get('DG_PF00-CorpID-Designa_Shop-Designers')

// role = SHOP_DESIGNER 
role = USER_ROLE_NAMES.get('DG_PF00-CorpID-Designa_Shop-Employees')

// role = SHOP_DESIGNER 
role = USER_ROLE_NAMES.get('DG_PF00-CorpID-Designa_Logistics')

// role = undefined
role = USER_ROLE_NAMES.get('some arbitrary string value which is not an enum value')

I already tried the following:

export const USER_ROLE_NAMES = new Map(Object.entries(UserRole).map(([key, value]: [string, UserRole]) => [value, key]));

but then the type of USER_ROLE_NAMES is Map<UserRole, string> and the map cannot be queried with a string.

If I invert the mapping

export const USER_ROLE_NAMES = new Map(Object.entries(UserRole).map(([key, value]: [string, UserRole]) => [key, value]));

then the type is correct, but the mapping is wrong ('DESIGNA_USER' => 'DG_PF00-CorpID-Designa_Users',... instead of 'DG_PF00-CorpID-Designa_Users' => 'DESIGNA_USER',...

3
  • Hmm, the point of enums is that the values are meant to be opaque; UserRole is strictly narrower than the union of the string literal values. It is considered a type error to use the string literal "DG_PF00-CorpID-Designa_Shop-Designers" where UserRole.SHOP_DESIGNER is expected. Trying to get the compiler to do otherwise would be "type unsafe" according to the language. So when you say you want a type safe reverse mapping it sort of sounds like you want the opposite? Maybe we're just using different terms. Commented Apr 8, 2022 at 13:09
  • 1
    Anyway when people want to peer into enum values it's often a sign that enums are not what they really want. If you replace the enum with a const object then the particular problem you're talking about goes away, see this. Of course there are other problems: Map<K, V>.get(k) returns V | undefined regardless of what k is; the data structure has no notion of "definitely present" keys; and you can't get() an arbitrary string key either unless you make K a string. What do you want to do about those two issues? Are they relevant to the question? Commented Apr 8, 2022 at 13:24
  • Wait a minute I just re-read the question and it looks like you don't want a reverse mapping at all; you just want to downcast strings to their equivalent enum values. So you want stackoverflow.com/questions/43804805/… or stackoverflow.com/questions/59376564/… etc maybe? Commented Apr 8, 2022 at 13:36

1 Answer 1

3

At runtime, the value of UserRole.SHOP_DESIGNER is actually 'DG_PF00-CorpID-Designa_Shop-Designers', not 'SHOP_DESIGNER'. So the mapping you are asking for would look like this (at runtime):

const theMapping ={
  'DG_PF00-CorpID-Designa_Shop-Designers': 'DG_PF00-CorpID-Designa_Shop-Designers',
  ...
}

If you want this "enum value" -> "enum member" mapping, you can construct it like this: TypeScript playground link

export enum UserRole {
  SHOP_DESIGNER = 'DG_PF00-CorpID-Designa_Shop-Designers',
  SHOP_EMPLOYEE = 'DG_PF00-CorpID-Designa_Shop-Employees',
  LOGISTICS_TEAM = 'DG_PF00-CorpID-Designa_Logistics',
}

const mapping: Map<string, UserRole> = new Map(Object.values(UserRole).map(
    (memberValue) => [`${memberValue}`, memberValue] as const
))

let role1 = mapping.get('DG_PF00-CorpID-Designa_Shop-Designers')
let role2 = mapping.get('unknown')
Sign up to request clarification or add additional context in comments.

1 Comment

that's exactly what I was looking for

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.