admin管理员组

文章数量:1355660

Lets suppose we have function with parameters:

function do(classId: number, schoolId: number, pupilId: number, teacherId: number, roomId: number) {
}

I need to call this function passing object with properties that should fill corresponding function's parameters like:

Case one:

let obj1 = {classId: 1, roomId: 3}; 

do(obj1); // passed only classId, roomId

Case two:

let obj2 = {schoolId: 5, pupilId: 4}; 

do(obj2); // passed only schoolId, pupilId

Lets suppose we have function with parameters:

function do(classId: number, schoolId: number, pupilId: number, teacherId: number, roomId: number) {
}

I need to call this function passing object with properties that should fill corresponding function's parameters like:

Case one:

let obj1 = {classId: 1, roomId: 3}; 

do(obj1); // passed only classId, roomId

Case two:

let obj2 = {schoolId: 5, pupilId: 4}; 

do(obj2); // passed only schoolId, pupilId
Share Improve this question edited Nov 30, 2018 at 14:39 Murat Karagöz 37.7k16 gold badges81 silver badges112 bronze badges asked Nov 30, 2018 at 14:30 POVPOV 12k40 gold badges128 silver badges229 bronze badges 9
  • 2 Take an object as parameter I guess, or am I overseeing something? – Marv Commented Nov 30, 2018 at 14:34
  • The problem is that object keys don't have a determined order. In most cases they probably list in the same order they appear on your screen, but that's not a guarantee. – Aaron Beall Commented Nov 30, 2018 at 14:35
  • 2 The order does not matter, just go for an object with optional properties and then evaluate which ones are set in the function. There is no reason to have an order – Marv Commented Nov 30, 2018 at 14:39
  • Sure, I can pass any set of properties – POV Commented Nov 30, 2018 at 14:39
  • Are you asking: how can I make the specific do() function accept an object instead of a list of parameters? Or are you asking: how can I make the specific do() function accept either an object or a list of parameters? Or are you asking: given a function which accepts a list of parameters, how can I transform it generically to a different function which accepts an object? – jcalz Commented Nov 30, 2018 at 14:44
 |  Show 4 more ments

3 Answers 3

Reset to default 6

If I got you correctly, you want this:

const Do: (
    arg: {
        classId?: number;
        schoolId?: number;
        pupilId?: number;
        teacherId?: number;
        roomId?: number;
    }
) => any = ({ classId, schoolId, pupilId, teacherId, roomId }) => {};

I replaced the list of parameters to a single parameter, that is an object destructuring pattern.

Note, that you cannot use do as an identifier name, so I changed it to Do.

Also classic JS functions are not very friendly with types and typescript, so I rewrote it using an arrow function.

The playground

The better approach

First, refactoring the function to take a single object param as in Nurbol's answer (which I upvoted) is IMO the better solution. Long argument lists of numbers are generally hard to use and prone to error.

The literal answer

That said, if you really want to convert an object key's to an argument list for an existing function (for example say do() is beyond your control and cannot be refactored) like your question states you do have some options.

A naive approach would be to use Object.values(), which will convert an object's values to an array which can be spread in as function arguments:

do(...Object.values(obj));

However the order of the values is not guaranteed (the same applies to all object key enumerations, like for..in or forEach()), so this isn't a good idea if the order of your function arguments matter, which it clearly does in your case.

To guarantee the correct param order you need to explicitly define the order of keys somehow. Here is an example of a generic function which takes an object and array of keys in order, then uses array.reduce() to produce the ordered argument list array:

function orderedArgs(obj: object, orderedKeys: string[]): any[] {
  return orderedKeys.reduce((args, key) => {
    args[orderedKeys.indexOf(key)] = obj[key as keyof object];
    return args;
  }, new Array(orderedKeys.length));
}

const argsOrder = ["classId", "schoolId", "pupilId", "teacherId", "roomId"];

const obj1 = { classId: 1, roomId: 3 }; 
doFn(...orderedArgs(obj1, argsOrder)); // passes: 1, undefined, undefined, undefined, 3

const obj2 = { schoolId: 5, pupilId: 4 };
doFn(...orderedArgs(obj2, argsOrder)); // passes: undefined, 5, 4, undefined, undefined

You can further abstract this with a helper function:

const callDo = (obj: object) => doFn(...orderedArgs(obj, ["classId", "schoolId", "pupilId", "teacherId", "roomId"]));

callDo({ classId: 1, roomId: 3 }); // passes: 1, undefined, undefined, undefined, 3

callDo({ schoolId: 5, pupilId: 4 }); // passes: undefined, 5, 4, undefined, undefined

Not sure if there any inbuilt functionality for this , but below code could work for you

function doSome(classId, 
    schoolId, 
    pupilId, 
    teacherId, 
    roomId)
    {
        console.log(classId, 
    schoolId, 
    pupilId, 
    teacherId, 
    roomId)
    }

    const Do = obj => {
        var classId , schoolId , pupilId , teacherId , roomId
        for(var k in obj){
           eval(k + "=" + obj[k])
        }
        doSome(classId , schoolId , pupilId , teacherId , roomId)
    } 

本文标签: javascriptHow to arrange object properties to parameters in functionStack Overflow