ThomasReggi
ThomasReggi

Reputation: 59365

Return enum from enum value lookup

I have an enum Animals and I am trying to create a function that takes a value and the entire enum object returns the value as an emum if it is valid.

enum Animals {
  WOLF = 'wolf',
  BADGER = 'badger',
  CAT = 'cat',
 }

const coerseEnum = <T> (s, E: T): T | undefined => {
  const keys = Object.keys(E);
  const values = keys.map(k => E[k as any]);
  const obj = lodash.zipObject(keys, values);
  const key = lodash.findKey(obj, item => item === s);
  if (!key) return undefined;
  return E[key];
};

const x: Animals | undefined = coerseEnum('cat', Animals);
console.log(x);

However it's not casting to Animals but typeof Animals.

Upvotes: 0

Views: 782

Answers (1)

Titian Cernicova-Dragomir
Titian Cernicova-Dragomir

Reputation: 249636

An enum has a type for the item of an enum (Animal) but also a type for the object that holds the values at runtime. This object is also named Animal, but it is not of type Animal since it contains all the entries for the enum. If we are starting from the type of the enum container object (typeof Animal) to get back to the type of the enum we need to write typeof Animal[keyof typeof Animal]

In your case, T is inferred to typeof Animal, the enum container object since that is what you are passing to the function. TO get back to the enum type we need to do T[keyof T]

enum Animals {
  WOLF = 'wolf',
  BADGER = 'badger',
  CAT = 'cat',
}

const coerseEnum = <T> (s: string, E: T): T[keyof T] | undefined => {
  const keys = Object.keys(E);
  const values = keys.map(k => E[k as any]);
  const obj = lodash.zipObject(keys, values);
  const key = lodash.findKey(obj, item => item === s);
  if (!key) return undefined;
  return E[key];
};

const x: Animals | undefined = coerseEnum('cat', Animals);
console.log(x);

Note We usually don't notice this, but when we use Animal in a type annotation it is the type of an enum item, when we use Animal as a value we are talking about the container object which is not of type Animal. Just wanted to make that clear in case the previous paragraph was not 100% clear

Upvotes: 3

Related Questions