DEV Community

druchan
druchan

Posted on

3

Enrich an object - Javascript Recipe

This scenario is very common in apps that interact with data from an API/backend service.

Let's say you get a customers list which looks like this:

let customers = [
  { id: 1, name: 'john', age: 28, city: 'denver' },
  { id: 2, name: 'bob', age: 25, city: 'kyoto' },
  { id: 3, name: 'angela', age: 44, city: 'mumbai' },
];
Enter fullscreen mode Exit fullscreen mode

And then you get, as an example, a kycCustomer:

let kycCustomer = {
  customerId: 1,
  kyc: true,
  createdOn: '2022-11-01',
};
Enter fullscreen mode Exit fullscreen mode

But when I want to use the kycCustomer to, say, show on the UI or use as input to another function, I have to also get the customer's name, age and city where customerId equals 1, and "enrich" this kycCustomer object with that data.

To do this, I use an enrich function where I tell which keys to match, which keys to extract and the function returns an enriched list.

const enrich =
  ({ match, extract = [], source = [] }) =>
  (inputObj) => {
    if (!match) return inputObj;
    if (!extract?.length) return inputObj;
    if (!source) return inputObj;
    if (!source?.length) return inputObj;
    let matchingItem = source.find(
      (s) => s[match.sourceKey] === inputObj[match.inputKey]
    );
    if (!matchingItem) return inputObj;
    return extract.reduce((acc, key) => {
      return {
        ...acc,
        [key]: matchingItem[key],
      };
    }, inputObj);
  };

// USAGE
let customers = [
  { id: 1, name: 'john', age: 28, city: 'denver' },
  { id: 2, name: 'bob', age: 25, city: 'kyoto' },
  { id: 3, name: 'angela', age: 44, city: 'mumbai' },
];

let kycCustomer = {
  customerId: 1,
  kyc: true,
  createdOn: '2022-11-01',
};

let result = enrich({
  match: { sourceKey: 'id', inputKey: 'customerId' },
  extract: ['name', 'age', 'city'],
  source: customers,
})(kycCustomer);

/*
result = {
  customerId: 1,
  kyc: true,
  createdOn: '2022-11-01',
  name: 'john',
  age: 28,
  city: 'denver'
}
*/
Enter fullscreen mode Exit fullscreen mode

Handling lists instead of objects

We handled a single object kycCustomer but what if we have to enrich an entire list/array of such objects?

let kycCustomers = [
  { customerId: 1, kyc: true, createdOn: '2022-11-01' },
  { customerId: 2, kyc: false },
  { customerId: 3, kyc: true, createdOn: '2022-09-01' },
];
Enter fullscreen mode Exit fullscreen mode

Simply mapping over and using the enrich function will solve this for us. Like so:

let customers = [
  { id: 1, name: 'john', age: 28, city: 'denver' },
  { id: 2, name: 'bob', age: 25, city: 'kyoto' },
  { id: 3, name: 'angela', age: 44, city: 'mumbai' },
];

let kycCustomers = [
  { customerId: 1, kyc: true, createdOn: '2022-11-01' },
  { customerId: 2, kyc: false },
  { customerId: 3, kyc: true, createdOn: '2022-09-01' },
];

let enrichedKycCustomers = kycCustomers.map((kycCustomer) =>
  enrich({
    match: { sourceKey: 'id', inputKey: 'customerId' },
    extract: ['name', 'age', 'city'],
    source: customers,
  })(kycCustomer)
);

/*
enrichedKycCustomers = [
  {
    customerId: 1,
    kyc: true,
    createdOn: '2022-11-01',
    name: 'john',
    age: 28,
    city: 'denver',
  },
  { customerId: 2, kyc: false, name: 'bob', age: 25, city: 'kyoto' },
  {
    customerId: 3,
    kyc: true,
    createdOn: '2022-09-01',
    name: 'angela',
    age: 44,
    city: 'mumbai',
  },
]
*/
Enter fullscreen mode Exit fullscreen mode

And in fact, because enrich is a higher-order function (notice how it takes one argument and returns a function that takes the inputObject argument), we can also condense the enrichedKycCustomers to this:

let enrichedKycCustomers = kycCustomers.map(
  enrich({
    match: { sourceKey: 'id', inputKey: 'customerId' },
    extract: ['name', 'age', 'city'],
    source: customers,
  })
);
Enter fullscreen mode Exit fullscreen mode

Top comments (2)

Collapse
 
artydev profile image
artydev

Great series thank you :-)

Collapse
 
zomars profile image
Omar López

This is exactly what I was looking for! I'm going to try to recreate it in TypeScript. Wish me luck.

AWS Security LIVE!

Tune in for AWS Security LIVE!

Join AWS Security LIVE! for expert insights and actionable tips to protect your organization and keep security teams prepared.

Learn More

👋 Kindness is contagious

Explore a sea of insights with this enlightening post, highly esteemed within the nurturing DEV Community. Coders of all stripes are invited to participate and contribute to our shared knowledge.

Expressing gratitude with a simple "thank you" can make a big impact. Leave your thanks in the comments!

On DEV, exchanging ideas smooths our way and strengthens our community bonds. Found this useful? A quick note of thanks to the author can mean a lot.

Okay