class BaseFunction {
static #allowInstantiation = false;
constructor(...args) {
if (!BaseFunction.#allowInstantiation) {
throw new Error(
"Why are you trying to use 'new'? Classes are so 2015! Use our fancy 'run' method instead!"
);
}
for (const [name, validator] of this.parameters()) {
this[name] = validator(args.shift());
}
}
parameters() {
return [];
}
body() {
return undefined;
}
static run(...args) {
BaseFunction.#allowInstantiation = true;
const instance = new this(...args);
BaseFunction.#allowInstantiation = false;
return instance.body();
}
}
class Add extends BaseFunction {
parameters() {
return [
["a", (x) => Number(x)],
["b", (x) => Number(x)],
];
}
body() {
return this.a + this.b;
}
}
console.log(Add.run(5, 3)); // 8
Oh sweet caffeine, race conditions in the constructor