I tinkered with this and was able to make this work against custom classes without much trouble.
let overloadTest = overload(
[String], function(value) {
console.log('we got a string', value);
},
[Number], function(value) {
console.log('we got a number', value);
},
[String, Number], function(s, n) {
console.log('we got a string AND a number', s, n);
}
[MyCustomClass], function(value) {
console.log('we got a MyCustomClass instance', value);
}
);
With this overload
implementation:
function overload(...overloads) {
const f = function(...args) {
let constructorArray = args.map(arg => arg.constructor);
let implIndex = f.overloads.findIndex(sig => {
return constructorArray.length === sig.length &&
constructorArray.every((o,i) => o === sig[i])
;
}) + 1;
if (implIndex > 0 && typeof(f.overloads[implIndex]) === 'function') {
return f.overloads[implIndex].apply({}, args);
} else {
const message = "There is no implementation that matches the provided arguments.";
console.error(message, constructorArray);
throw Error(message);
}
};
f.overloads = overloads;
return f;
};
This doesn't work on instance methods just yet. But, it could be extended.
Also, the arguments list refers directly to constructors (as opposed to a strings), which means you could extend with additional validation if you like -- for example, ensuring that each argument type is actually a function/constructor at overload()
time. You could also conceivably create a version of overload()
that performs DI.