
Function overloading with a variable number of arguments.
ce@neckar.it
Let’s assume we need to write a function in TypeScript that adds samples to some kind of store.
Additionally, we want to be able to pass a single sample, several samples or an array of samples to that function.
That is, we want to be able to write the following code:
// sample1, ..., sample5 are of type Sample
addSamples(sample1);
addSamples([sample4, sample5]);
addSamples(sample2, sample3);
How would we do that? A function that takes a single sample can be easily written:
function addSamples(sample: Sample): void {
const store = [];
store.push(sample);
// do something with store
}
addSamples(sample1); // works
addSamples([sample4, sample5]); // error
addSamples(sample2, sample3); // error
So far so good. A function that takes an array of samples would look like this:
function addSamples(samples: Array<Sample>): void {
const store = [];
store.push(...samples);
// do something with store
}
addSamples(sample1); // error
addSamples([sample4, sample5]); // works
addSamples(sample2, sample3); // error
Still not difficult. How would a function look like that accepts an arbitrary number of samples?
This is where „varargs“ come in handy:
function addSamples(...samples: Array<Sample>): void {
const store = [];
store.push(...samples);
// do something with store
}
addSamples(sample1); // works
addSamples([sample4, sample5]); // error
addSamples(sample2, sample3); // works
Alright, but the goal is to have a single function that does everything at once.
How would such a function be implemented?
For this we need function overloading:
function addSamples(sample: Sample): void;
function addSamples(...samples: Array<Sample>): void;
function addSamples(sample: Array<Sample> | Sample, ...samples: Array<Sample>): void {
const store = [];
if (Array.isArray(sample)) {
store.push(...sample);
} else {
store.push(sample);
}
store.push(...samples)
// do something with store
}
addSamples(sample1); // works
addSamples([sample4, sample5]); // works
addSamples(sample2, sample3); // works
With function overloading the signature of the implementing function must be the union of all signatures.
One can certainly argue if this solution is something to strive for.
Perhaps a more straight forward approach would be to have several functions with different names.
But in the end this was a requirement from a real-world project.
Feel free to adopt it to your needs.