Skip to content

Instantly share code, notes, and snippets.

@DarkoKukovec
Forked from rauschma/enum.ts
Last active December 29, 2019 16:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save DarkoKukovec/71621f404a289ac8d255c6d071416d1e to your computer and use it in GitHub Desktop.
Save DarkoKukovec/71621f404a289ac8d255c6d071416d1e to your computer and use it in GitHub Desktop.
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