0

I have a function which takes four parameters, among which the 1st parameter is required, the 2nd & 3rd are optional, the 4th has a default value:

class MyClass {
   static myFunc(param1: string, param2? : string, param3? : string, param4:boolean=true) 
   {
      ...
   }
}

In my caller, I would like to provide the value of 1st parameter and override the 4th boolean. How to do that? I can't do MyClass.myFunc("foo", false). Should I re-design the function signature? What is the convention in TypeScript to have a function like that?

jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
user842225
  • 5,445
  • 15
  • 69
  • 119
  • This isn't specific to TypeScript - you can't do that _in JavaScript_. You'd have to explicitly call e.g. `MyClass.myFunc("foo", undefined, undefined, false)`. – jonrsharpe Dec 01 '21 at 11:22
  • I am seeking for the alternative way if I can't do that. I know it most likely can not be in this way like my question said & I'd be glad to hear the typescript way. – user842225 Dec 01 '21 at 11:23
  • 1
    Does this answer your question? [Skip arguments in a JavaScript function](https://stackoverflow.com/questions/32518615/skip-arguments-in-a-javascript-function) – jonrsharpe Dec 01 '21 at 11:25
  • 1
    There isn't "the typescript way" - TypeScript lets you describe the interface and checks you're calling it correctly, but doesn't change the fact that this doesn't exist in the runtime JS. JavaScript doesn't have named parameters, you can't do `MyClass.myFunc("foo", param4=false)`, but you can approximate them by passing an _object_ `MyClass.myFunc({ param1: "foo", param4: false })` - see https://stackoverflow.com/q/11796093/3001761. But again this is nothing to do with TS and you can research the options in JS. – jonrsharpe Dec 01 '21 at 11:26
  • @jonrsharpe Thank you for your above comment. I would appreciate more if you make an answer for your comment. & I already mentioned in my question I know I can't do `MyClass.myFunc("foo", param4=false)`, my just don't know what is the right way. So, ask in SO. It feels to me like people who are not experienced with something should get more experiences first before asking question here... I don't feel right to have this feeling in this community. – user842225 Dec 01 '21 at 11:33
  • _"I already mentioned in my question I know I can't do `MyClass.myFunc("foo", param4=false)`"_- you said you knew you couldn't do `MyClass.myFunc("foo", false)`, which isn't quite the same thing. The point of the duplicate system is to direct you to the existing answers, rather than writing out the same options over again. _"It feels to me like people who are not experienced with something should get more experiences first before asking question"_ - yes, I think that's true. Other resources (e.g. structured tutorials) are more appropriate, asking good questions isn't trivial. – jonrsharpe Dec 01 '21 at 11:35
  • The canonical definitions are in the [help]. See also [meta], e.g. https://meta.stackoverflow.com/q/413320/3001761 – jonrsharpe Dec 01 '21 at 11:42
  • The line is vague, but if you think in that way, be it. Not convincing to my case. – user842225 Dec 01 '21 at 11:47
  • @user842225 upvoted :D. In my opinion, you have very complicated requirements for function arguments. Just Keep it Stupid Simple. Maybe it worth splitting into two functions, I mean curry it, or make one argument as an object where each key represents each argument. In order to avoid any downvoting sometimes it worth providing more examples of what did you try or some test cases for your requirements. – captain-yossarian from Ukraine Dec 01 '21 at 11:49

2 Answers2

0
  1. You should redefine the order and the usage of the parameters in your function.

  2. Use param?:type

This way you can overload the function call without explicitly sending unnecessary undefined as arguments.

const func = (a:number, b:boolean = true, c?:string, d?:string) => {
    console.log(a, b, c, d)
}

func(1)
func(1, false)
func(1, false, "Hello")
func(1, false, "Hello", "World")

In your case:

class MyClass {
   static myFunc(param1:string, param2:boolean = true, param3?:string, param4?:string) 
   {
      ...
   }
}
Yash Sonalia
  • 378
  • 2
  • 8
0

Here are a couple of ways to achieve the API you asked about:

TS Playground link

class MyClass {
  // the method in your question
  static myFunc (
    param1: string,
    param2?: string,
    param3?: string,
    param4 = true,
  ): void {
    console.log([param1, param2, param3, param4]);
  }

  // parameters reordered
  static myRefactoredFunc (
    param1: string,
    param4 = true,
    param2?: string,
    param3?: string,
  ): void {
    console.log([param1, param2, param3, param4]);
  }
}

// if you can't modify the class, you can create a function with the 
// parameters ordered by your preference, which calls the original method
// in the function body and returns its return value
const myFunc = (
  param1: Parameters<typeof MyClass['myFunc']>[0],
  param4?: Parameters<typeof MyClass['myFunc']>[3],
  param2?: Parameters<typeof MyClass['myFunc']>[1],
  param3?: Parameters<typeof MyClass['myFunc']>[2],
): ReturnType<typeof MyClass['myFunc']> => MyClass.myFunc(param1, param2, param3, param4);

// these are all equivalent
MyClass.myFunc('foo', undefined, undefined, false);
MyClass.myRefactoredFunc('foo', false);
myFunc('foo', false);
jsejcksn
  • 27,667
  • 4
  • 38
  • 62