Skip to content

Instantly share code, notes, and snippets.

@yurkimus
Last active June 26, 2024 18:23
Show Gist options
  • Save yurkimus/52d78f45246ec56b63e74f4f8d26fe28 to your computer and use it in GitHub Desktop.
Save yurkimus/52d78f45246ec56b63e74f4f8d26fe28 to your computer and use it in GitHub Desktop.
Implementation of Enumeration Prototype to simplify work with enumerations. Type definitions are included.
interface DoubleEnumeration<const Tuples extends ReadonlyArray<readonly [any, any]>> {
[(Key in Tuples[number]) as Key[0]]: Key[1];
[(Key in Tuples[number]) as Key[1]]: Key[0];
has(key: Tuples[number][number]): boolean;
keys(): IterableIterator<Tuples[number][0]>;
values(): IterableIterator<Tuples[number][1]>;
entries(): IterableIterator<Tuples>;
[Symbol.iterator](): IterableIterator<Tuples>;
}
interface SingleEnumeration<const Values extends ReadonlyArray<any>> {
[Key in Values[number]]: Key;
has(key: Values[number]): boolean;
keys(): IterableIterator<Values[number]>;
values(): IterableIterator<Values[number]>;
entries(): IterableIterator<{ [Key in keyof Values]: [Values[Key], Values[Key]] }[number]>;
[Symbol.iterator](): IterableIterator<
{ [Key in keyof Values]: [Values[Key], Values[Key]] }[number]
>;
}
interface EnumerationConstructor {
new <const Tuples extends ReadonlyArray<readonly [any, any]>>(
enumerationInit: Tuples
): DoubleEnumeration<Tuples> & Enumeration;
new <const Values extends ReadonlyArray<any>>(
enumerationInit: Values
): SingleEnumeration<Values> & Enumeration;
of<const Tuples extends ReadonlyArray<readonly [any, any]>>(
enumerationInit: Tuples
): DoubleEnumeration<Tuples> & Enumeration;
of<const Values extends ReadonlyArray<any>>(
enumerationInit: Values
): SingleEnumeration<Values> & Enumeration;
}
interface Enumeration {
[Symbol.toStringTag]: string;
}
declare var Enumeration: EnumerationConstructor;
function Enumeration(enumerationInit) {
if (
Array.isArray(enumerationInit) &&
enumerationInit.length &&
enumerationInit.every(
(parameter) =>
typeof parameter == 'string' ||
typeof parameter == 'number' ||
typeof parameter == 'boolean'
)
) {
for (let index = 0; index < enumerationInit.length; index++) {
this._keys = this._values = enumerationInit
this[enumerationInit[index]] = enumerationInit[index]
}
} else if (
Array.isArray(enumerationInit) &&
enumerationInit.length &&
enumerationInit.every(
(parameter) =>
Array.isArray(parameter) &&
parameter.length == 2 &&
(typeof parameter[0] == 'string' ||
typeof parameter[0] == 'number' ||
typeof parameter[0] == 'boolean') &&
(typeof parameter[1] == 'string' ||
typeof parameter[1] == 'number' ||
typeof parameter[1] == 'boolean')
)
) {
for (let index = 0; index < enumerationInit.length; index++) {
this._keys = []
this._values = []
this._keys.push(enumerationInit[index][0])
this._values.push(enumerationInit[index][1])
this[enumerationInit[index][0]] = enumerationInit[index][1]
this[enumerationInit[index][1]] = enumerationInit[index][0]
}
} else {
throw new TypeError(
"Failed to construct 'Enumeration': The provided value is not of type '(sequence<USVString> or sequence<sequence<USVString>>)'>"
)
}
}
Enumeration.of = function (enumerationInit) {
return new Enumeration(enumerationInit)
}
Enumeration.prototype.has = function (key) {
return Boolean(this[key])
}
Enumeration.prototype.keys = function* () {
for (index = 0; index < this._keys.length; index++) yield this._keys[index]
}
Enumeration.prototype.values = function* () {
for (index = 0; index < this._values.length; index++) yield this._values[index]
}
Enumeration.prototype.entries = function* () {
for (index = 0; index < this._keys.length; index++) yield [this._keys[index], this._values[index]]
}
Enumeration.prototype[Symbol.iterator] = function* () {
yield* this.entries()
}
Enumeration.prototype[Symbol.toStringTag] = 'Enumeration'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment