Search code examples
javascriptecmascript-6named-parametersspread-syntax

How to spread object as method input parameter but not as arguments array?


I have a function expecting multiply parameter and an input object that contains information with same key name as parameter field name, take a small example, e.g

const input = {
   firstName: 'first',
   lastName: 'last',
   age: 19
}

function test(firstName, lastName, age, otherThings) {
   console.log('firstName: ', firstName):
   console.log('lastName: ', lastName):
   console.log('age: ', age):
}

Right now I have to call it either by the dot notation of my input object, or using the spread which turns into an array then use index there

// call method 1
test(input.firstName, input.lastName, input.age, 'other');

// call method - I know it's kinda ugly but just an available way
test(...[input][0], ...[input][1], ...[input][2], 'other');

I am wondering if there is any other way that can use the idea of spread operator but instead of mapping into an array, spread the object as flatMap then automatically map them into the method parameter fields, I know the ...input may not work as input was an object not an array so it's not iterable.

// is it possible?
test(...input.someAction?, 'other');

This would help when my input object as pretty large and want to figure out a smart way of executing it without modifying the method signature, please note I CANNOT modify the method signature or implementation, we can consider it as an interface method and we can only determine how to execute it on our side


Solution

  • test(...Object.values(input), 'other')
    

    would kinda work, but of course that will break as soon as the object gets more properties or contains them in a different order - it will not put properties into arguments for the respective parameter names, that is impossible. For a proper solution, you should change the test function to take an options object:

    function test(options) {
       console.log('firstName: ', options.firstName):
       console.log('lastName: ', options.lastName):
       console.log('age: ', options.age):
    }
    

    or with destructuring:

    function test({firstName, lastName, age, otherThings}) {
       console.log('firstName: ', firstName):
       console.log('lastName: ', lastName):
       console.log('age: ', age):
    }
    

    Then you can call it properly using

    test(input)
    

    or also with object spread

    test({...input, otherThings: 'other'})