export interface EnumExt> { Readable: (value: E[keyof E]) => keyof E; } export namespace Enum { export type KeyOf> = Exclude>; } export function Enum>, string | number>>( name: string, record: E, ): E & EnumExt { Object.defineProperty(record, 'name', { value: name, writable: false, configurable: false, enumerable: false, }); // Readable const reversed = (Object.entries(record) as [keyof E, E[keyof E]][]).reduce( (acc, [key, value]) => { acc[value] = key; return acc; }, {} as Record, ); Object.defineProperty(record, 'Readable', { value: (value: E[keyof E]) => reversed[value] || `${name}(${value})`, writable: false, configurable: false, enumerable: false, }); return record as E & EnumExt; }