«Полиморфные» конструкторы в основном плохая идея, потому что их сложно программировать (как вы уже знаете), а также сложнее отследить в коде. Вместо этого я бы предложил использовать специализированные фабричные функции для каждого возможного типа аргумента. Пример:
class Enum {
constructor(pairs) {
for (let [name, val] of pairs)
this[name] = val;
}
static from(names) {
return new this([...names.entries()].map(([k, v]) => [v, k]));
}
static of(...names) {
return this.from(names);
}
static fromObject(obj) {
return new this(Object.entries(obj));
}
}
const enums = {
Size: Enum.of('small', 'big', 'huge'),
Level: Enum.fromObject({'first': {txt: 'h1'}, 'second': {txt: 'h2'}, 'third': {txt: 'h3'}}),
Color: Enum.from(['red', 'orange', 'blue']),
Flags: new Enum([['read', 1], ['write', 2], ['execute', 4]])
};
console.log(enums.Size.huge)
console.log(enums.Color.orange)
console.log(enums.Level.third)
console.log(enums.Flags.execute)