2

I want to pass optionally an array to a function or an array setting it to a default value.

This is the typical way: function myfunc(...values : Array<number>)

I know that I can do it this way, but I don't know how to set it to allow this function calls:

myfunc()
myfunc(1)
myfunc(1,2)
myfunc([1, 2])

with the above, all except myfunc() are supported. How can I make it?

Filip Seman
  • 1,252
  • 2
  • 15
  • 22
jlanza
  • 1,208
  • 3
  • 23
  • 43

3 Answers3

1

Here it is:

function myfunc(...values : Array<number> | [Array<number>]) {}

myfunc()
myfunc(1)
myfunc(1,2)
myfunc([1, 2])

myfunc('invalid')
myfunc([1, 2], [3, 4])

Here is a preview where you can check the result.

Caerbannog
  • 790
  • 3
  • 8
  • 1
    Doesn't this make `myfunc([1, 2], [3, 4])` valid which is not intended behaviour? – Hive7 May 16 '21 at 09:37
  • 1
    @Hive7 Right. I've updated the answer to fix it. – Caerbannog May 16 '21 at 09:45
  • It still doesn't work quite as you would expect, since the type inside the implementation is confused between a singleton array and an array of values. Consider myfunc([1, 2, 3, 4]), the function treats it as [[1, 2, 3, 4]] which is not what is desired here – Hive7 May 16 '21 at 09:54
1

You can define your two overloads and then specify the logic in a single function. Something like below should work.

function myfunc(...values : Array<number>): number;
function myfunc(values : Array<number>): number;

function myfunc(value : (Array<number> | number), ...values : Array<number>): number {
    if (typeof value === 'number') {
        values.unshift(value);
    } else if (value === undefined) {
        values = [];
    } else {
        values = value;
    }

    // logic

    return values.length;
}

myfunc(); // correct
myfunc(1); // correct
myfunc(1, 2); // correct
myfunc([1, 2]); // correct
myfunc(1, 2, 3, 4); // correct
myfunc([1, 2, 3]); // correct
// myfunc([1, 2, 3, 4], 5, 6); // error
// myfunc([1, 2], [3, 4]); // error

console.log(myfunc(1, 2, 3)) // 3
console.log(myfunc([1, 2, 3])) // 3

Notice how because we have not defined an interface for an array followed by values, the final example results in an error which I think is the expected behaviour. An example can be seen here. We have to check for undefined here as the transpiled JavaScript does not take into account the different function overloads, and instead provides a single implementation where value can be undefined.

Hive7
  • 3,599
  • 2
  • 22
  • 38
  • I like explicit way of function overrides, because it's more like documentation and it makes you think about multiple logic flows. – Filip Seman May 16 '21 at 09:49
  • So there is no way of using the ? operator like `...value?` ? – jlanza May 16 '21 at 10:14
  • Not for your desired behaviour as `?` denotes that undefined is allowed – Hive7 May 16 '21 at 10:16
  • And what about if I set a default value? let's say that value can be [ 0 ] as default. Then would it be possible? could you please give a hint in case it is. – jlanza May 16 '21 at 11:05
  • Unfortunately, a rest parameter cannot have a default value. See [here](https://stackoverflow.com/questions/42650594/is-it-possible-to-set-default-parameter-value-on-a-rest-parameter) for more details – Hive7 May 16 '21 at 11:21
-2

Can you use like this in a simple way !!!

function a(k = []) {
    console.log(k)
}

a();
a(1);
a([1]);
a([1, 2, 3]);
Gopi krishna
  • 308
  • 1
  • 9
  • When I try this code on https://www.typescriptlang.org/play, it gives lots of errors... – Peter B May 16 '21 at 10:00
  • @PeterB, I have written the above code in Js, not in Ts. If you want to run the same code in TS, please change the function to , function a(k:any=null) { console.log(k) } – Gopi krishna May 16 '21 at 16:47