Issue
I want to determine whether an item should be looped and pushed, or directly pushed to an array.
For this, I have created the following code:
interface Item {
prop1: string;
prop2: string;
prop3: string[];
}
For prop1
, prop2
, prop3
I need its data in a single string array for each property. So I want to get the corresponding function pointer:
const items = [...] as Item[];
const collectProperties = ["prop1", "prop2", "prop3"];
// Contains the function pointers for every prop in collectProperties
const appendOperations = [] as ((array: string[], element: any) => void)[];
// Extract function pointers for each prop-type
collectProperties.forEach((element, index) => {
appendOperations.push(
Array.isArray(items[0][element as keyof Item])
? (array: string[], element: any) =>
element.forEach((value) => array.push(String(value)));
: (array: string[], element: any) =>
array.push(String(element))
);
});
// Appending items based on its type
items.forEach((item) => {
appendOperations.forEach((fn, index) => {
fn(
// ... some array,
// ... some value
);
});
});
I feel like there should be a more compact, elegant way of doing this. I know this can be done in the loop itself as well, but this means there will be an if-check in every property of every element, which is not desired when processing huge chunks of data. Help is appreciated.
Solution
There are a couple of things you can do to tighten up the first bit:
- Make
collectProperties
an array ofkeyof Item
rather than an array of strings, so you don't have to use a type assertion later - Use
map
to buildappendProperties
rather than creating the array and pushing to it, since it's a one-to-one operation; this also lets you infer its type from themap
return type
// *** Use the type on the array so you don't have to use a type assertion later
const collectProperties: (keyof Item)[] = ["prop1", "prop2", "prop3"];
// Contains the function pointers for every prop in collectProperties
// *** `map` is a bit more idiomatic and helps a bit with setting types
const appendOperations = collectProperties.map(propName => {
// *** Avoiding using `items` for this check since there's no need to make this function
// dependent on `items`
return propName === "prop3"
? (array: string[], element: any) =>
element.forEach((value: any) => array.push(String(value)))
: (array: string[], element: any) =>
array.push(String(element));
});
// Appending items based on its type
// *** `forEach` is fine, but you could also avoid making functions using `for-of`
for (const item of items) {
for (const fn of appendOperations) {
fn(
// ... some array,
// ... some value
);
}
}
For the loop at the end, I couldn't get enough of an idea what it should be doing, but you might consider for-of
rather than forEach
just to avoid creating unnecessary functions, etc.
Answered By - T.J. Crowder
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.