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

SurveyJS custom survey software

JavaScript UI Libraries for Surveys and Forms

SurveyJS lets you build a JSON-based form management system that integrates with any backend, giving you full control over your data and no user limits. Includes support for custom question types, skip logic, integrated CCS editor, PDF export, real-time analytics & more.

Learn more

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.

nextjs tutorial video

Youtube Tutorial Series 📺

So you built a Next.js app, but you need a clear view of the entire operation flow to be able to identify performance bottlenecks before you launch. But how do you get started? Get the essentials on tracing for Next.js from @nikolovlazar in this video series 👀

Watch the Youtube series