1

I have a method in typescript as below using named parameters

public foo({x, y, z , m , n} : {x:string, y: number, z: number, m?:string, n?:number}) {
}

parameters m and n will be provided from another object like

const default = { m : 'M', n :10, o:6 }

Now I want to call foo like below and I want default parameters will be added without explicitly passing them in the call

  foo({x:'x', y: 5, z: 0})

So my question is how to apply default in the body of foo or somehow intercepting foo before call and apply default

public foo({x, y, z , m , n} = {x:string, y: number, z: number, m?:string, n?:number}) {
   // for example how to apply default here

}

Please note for simplicity I reduced number of parameters

Also I know these below solutions already I am looking for something with less boilerplate code

public foo({x, y, z , m , n} = {x:string, y: number, z: number, m?:string, n?:number}) {
   if (!m) {
     m = default.m;
   }
   if (!n) {
     n = default.n;
   }

}

or

foo({...default, x:'x', y: 5, z: 0 });
1
  • You can probably do something with decorators here but I am not really sure it's going to be much less boilerplate than foo({...default, x:'x', y: 5, z: 0 });. Maybe slightly more reusable, though. Commented May 28, 2020 at 16:39

3 Answers 3

2

For merge, u need to use merge using de-structure. default assignment will not work here. The default assignment is for work only if the object is undefined while passing value. So you need to merge the default value with passed value.

Please check comment in code.

interface Foo {
  x: string;
  y: number;
  z: number;
  m?: string;
  n?: number;
  o?: number;
}
const defaultValue = { m: "M", n: 10, o: 6 } as Foo;
class A {
  public foo(props: Foo) {
    const { x, y, z, m, n } = { ...defaultValue, ...props };
    console.log(x, y, z, m, n);
  }
  public foo2({ x, y, z, m = defaultValue.m, n = defaultValue.n }: Foo) {
    // this will work, but verbose
    console.log(x, y, z, m, n);
  }
  public foo1({ x, y, z, m, n }: Foo = defaultValue) {
    // this will work only if foo1 called without argument
    console.log(x, y, z, m, n);
  }
  public print() {
    this.foo({ x: "x", y: 5, z: 0 }); // x 5 0 M 10
    this.foo1(); // undefined undefined undefined 'M' 10
    this.foo1({ x: "x", y: 5, z: 0 }); // x 5 0 undefined undefined
    this.foo2({ x: "x", y: 5, z: 0 }); // x 5 0 M 10
  }
}
const a = new A();
a.print();

foo and foo2 function will work. However, foo2 is very verbose if more then few arguments. Use Object.assign() or {...} to merge value.

Sign up to request clarification or add additional context in comments.

Comments

1

You can just add a default value in the parameter itself like below:

public foo({x, y, z , m = 'a' , n = 10} = {x:string, y: number, z: number, m?:string, n?:number}) {
}

If you pass a value, default value will be overridden. With this way, you dont even need an if to check the presence of the value.

and you can still call the method as:

foo({...default, x:'x', y: 5, z: 0 });

Comments

0

How about combining and destructing object inside function?

type someType = {x:string, y: number, z: number, m?:string, n?:number};
const initialValues = { m : 'M', n :10, o:6 }

function foo(obj: someType) {
  const {x, y, z , m , n} = {
    ...initialValues,
    ...obj
  }

}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.