Scenario:
I am making a generic function that returns a boolean depending on logical AND statements, however, the function being generic accept multiple type of objects and arrays, and the statements can vary depending on the objects.
at the moment I have something like this
private async myFunction(
myArray: myArrObj[],
myObj : myObj,
): Promise<boolean> {
return (
myArr.some(
(a) =>
a.status1=== "*" ||
a.status1 === myObj.status1.status1Id
) &&
myArr.some(
(a) =>
a.status2=== "*" ||
a.status2 === myObj.status2.status2Id
) &&
myArr.some(
(a) =>
a.status3=== "*" ||
a.status3 === myObj.status3.status3Id
) &&
myArr.some(
(a) =>
a.status4=== "*" ||
a.status4 === myObj.status4.status4Id
)
)
}
the issue is not being able to know what kind of array is passed and how many checks are needed, how can I make a return? My idea was storing each array.some method in an array and join them with " && ", this approach would require to execute something from a string, which I'm not sure is the most secure thing to do, since eval is not secure at all.
to get the myObj statuses I could just use a for loop and store the the the property in a string. I can't come up with a good solution, so feel free to propose something new if my idea is not good enough
As noted by others in the comments, it would help if you had a reproducible example with sample data. That being said, from your comment:
but the statuses and id's have different names, some id's are .nameId, and some are just .id , but the statuses themselves have the same name, so instead of status1 and obStatus1 it really should be status1 and status1
Breaking this down:
but the statuses and id's have different names, some id's are .nameId, and some are just .id
You could try to see if nameId exists and fall back to id.
but the statuses themselves have the same name, so instead of status1 and obStatus1 it really should be status1 and status1
When myArr entries share keys with myObj, then you could simply loop through myObj's keys.
async function myFunction(myArr, myObj) {
// Fallback value for if .nameId and .id both don't exist.
// Falling back to `undefined` would cause a bug / false positives.
const notFound = Symbol();
// Loop through every key:value pair in the input object.
return Object.entries(myObj).every(([myObjKey, myObjValue]) => {
// Handle both `.nameId` and `.id`
const id = myObjValue[`${myObjKey}Id`] ?? myObjValue.id ?? notFound;
// If `myArrObj`'s children only ever contain exactly
// a single key { status2: { someRandomKey: 123 } }, then you
// could use myObjValue[Object.keys(myObjValue)[0]];
// For this key--for example "status1"--is there *any* array entry
// in `myArrObj` that has the same key and value or "*"?
return myArr.some((a) => {
return a[myObjKey] === '*' || a[myObjKey] === id;
});
});
}
With the following sample data:
const sampleArr = [
{ status3: "*" },
{ status2: 234 },
{ status1: 123, thisIsAnUnusedKey: true },
{ status4: 456 },
{ name: "Foobar" },
{ thisIsAnUnusedArrayEntry: true },
];
const sampleObj = {
status1: {
status1Id: 123,
},
status2: {
status2Id: 234,
},
status3: {
status3Id: 345,
},
status4: {
// Different key
id: 456,
},
name: {
// Different dataType
nameId: "Foobar"
}
};
myFunction(sampleArr, sampleObj).then(console.log); // Logs `true`