How to build a type from enum values in TypeScript?

[@hackape 's solution][1] is great, but I found minimal duplication extending his solution as below:

type ReverseMap<T extends Record<keyof T, any>> = {
  [V in T[keyof T]]: {
    [K in keyof T]: T[K] extends V ? K : never;
  }[keyof T];
}

const Map = {
  'FOO': "foo" as "foo",
  'BAR': "bar" as "bar",
}

const reverseMap: ReverseMap<typeof Map> = Object.entries(Map).reduce((rMap, [k, v]) => {
  rMap[v] = k;
  return rMap;
}, {} as any);

export type Values = keyof typeof reverseMap; // 'foo' | 'bar';

ReverseMap implementation is well explained [here][2]

[1]: https://stackoverflow.com/a/60768453/5519365 [2]: https://stackoverflow.com/a/55209457/5519365

Update: I found a much simpler solution for ReverseMap

const Obj = {
 FOO: 'foo',
 BAR: 'bar',
} as const;

type ReverseMap<T> = T[keyof T];

export type Values = ReverseMap<typeof Obj>; // 'foo' | 'bar';

Yes, you can use enum values as keys. And you can use a mapped type like the standard library's Record<K, V> to prevent repetition:

enum FooKeys {
  FOO = 'foo',
  BAR = 'bar',
}

// probably all you need, but it's a type alias
type FooType = Record<FooKeys, string>;

// if you need an interface instead you can do this
interface FooInterface extends FooType {};

And you can verify that it works:

declare const foo: FooInterface;
foo.foo; // okay
foo[FooKeys.FOO]; // okay

foo.bar; // okay
foo[FooKeys.BAR]; // okay

foo.baz; // error

Does that work for you? Good luck!