-
-
Save DarkoKukovec/71621f404a289ac8d255c6d071416d1e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
interface IEnum<T = void> { | |
key: string; | |
value: T; | |
} | |
interface IEnumConstructor<T = void> { | |
new(value: T): IEnum<T>; | |
enumKeys: Set<string>; | |
enumValues: Set<IEnum<T>>; | |
} | |
class EnumClass<T = void> { | |
protected static readonly _enumList: Array<EnumClass> = []; | |
private static _enumValues: Set<EnumClass>; | |
public static get enumValues(): Set<EnumClass> { | |
return this._enumValues || (this._enumValues = new Set(this._enumList.filter((item) => item.key))); | |
} | |
private static _enumKeys: Set<string>; | |
public static get enumKeys(): Set<string> { | |
return this._enumKeys || (this._enumKeys = new Set(this._enumList.map((item) => item.key).filter(Boolean))); | |
} | |
private _key?: string; | |
public get key(): string { | |
return this._key || (this._key = (Object.keys(this.constructor).find((itemKey: string) => (this.constructor as any)[itemKey] === this) as string)); | |
} | |
constructor(public value: T) { | |
(this.constructor as typeof EnumClass)._enumList.push(this as unknown as EnumClass); | |
} | |
public toString(): string { | |
return `${this.constructor.name}.${this.key}`; | |
} | |
} | |
function Enum<T = void>() { | |
return class EnumClassItem extends EnumClass<T> { | |
protected static readonly _enumList: Array<EnumClass> = []; | |
} as unknown as IEnumConstructor<T>; | |
} | |
// Example: | |
// Define the enum | |
class YesNo extends Enum<number>() { | |
static Yes = new YesNo(1); | |
static No = new YesNo(2); | |
} | |
// Works with multiple enums | |
class YesNoMaybe extends Enum<string>() { | |
static Yes = new YesNoMaybe('Yeah'); | |
static No = new YesNoMaybe('Nah'); | |
static Maybe = new YesNoMaybe('Meh'); | |
} | |
// Can be done, but won't influence the enum | |
const maybe = new YesNo(3); | |
const iDontKnow = new YesNo(4); | |
const canYouRepeatTheQuestion = new YesNo(5); | |
// Expected results | |
console.log(String(YesNo.Yes)); // 'YesNo.Yes' | |
console.log(YesNo.enumKeys.has('Yes')); // true | |
console.log(YesNo.enumKeys.has('Maybe')); // false | |
console.log(YesNo.enumKeys.has('Yesss!')); // false | |
console.log(YesNo.enumKeys.size); // 2 | |
console.log(YesNo.enumValues.size); // 2 | |
console.log(YesNo.Yes.key); // Yes | |
console.log(YesNo.Yes.value); // 1 | |
console.log(YesNoMaybe.enumKeys.size); // 3 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment