DEV Community

Marcos Henrique
Marcos Henrique

Posted on

Optional handmade chaining 🤓

In my country (Brazil) we have a saying, who doesn't have a dog hunting with a cat.

I've been working on a project where we could not update the latest version of the node and there was no possibility to put the babel or even the experimental flag --harmony, because we had some enterprise restrictions to do something like that.

So it's time to use creativity ✨

const optionalChainingByPath = (object, path) => {
  const pathSplitted = path.split('.')

  const [firstKey] = pathSplitted

 if (object[firstKey] == null || object[firstKey] ==='' ) { return null }
  if (typeof object[firstKey] === 'object') {
    pathSplitted.shift()
    return optionalChainningByPath(object[firstKey], pathSplitted.join('.'))
  }

  return object[firstKey]
}

⭐ Must Read: wakeupmh/optional handmade chaining - สรุปดราม่าล่าสุด ⭐ Must Read: wakeupmh/optional handmade chaining - สรุปดราม่าล่าสุด

Usage:

const makeResponse = patient => ({
  name: optionalChainingByPath(patient, 'personalInformation.name'),
  gender: optionalChainingByPath(patient, 'personalInformation.gender'),
  cardNumber: optionalChainingByPath(patient, 'personalInformation.cardNumber')
})
⭐ Must Read: wakeupmh/optional handmade chaining - สรุปดราม่าล่าสุด ⭐ Must Read: wakeupmh/optional handmade chaining - สรุปดราม่าล่าสุด

It's ok but unamused 😒

Let's make this cool enough 🥳

We'll use partial functions to transform this boring function into a fancy function ✨

const optionalChainingByPath = object => path => {
  const pathSplitted = path.split('.')

  const [firstKey] = pathSplitted

  if (object[firstKey] == null || object[firstKey] === '') {
    return null
  }

  if (typeof object[firstKey] === 'object') {
    pathSplitted.shift()
    return optionalChainingByPath(object[firstKey], pathSplitted.join('.'))
  }

  return object[firstKey]
}
⭐ Must Read: wakeupmh/optional handmade chaining - สรุปดราม่าล่าสุด ⭐ Must Read: wakeupmh/optional handmade chaining - สรุปดราม่าล่าสุด

Usage:

const makeResponse = patient => {
  return {
    name: optionalChaining('personalInformation.name'),
    gender: optionalChaining('personalInformation.gender'),
    cardNumber: optionalChaining('personalInformation.cardNumber')
  }
}
⭐ Must Read: wakeupmh/optional handmade chaining - สรุปดราม่าล่าสุด ⭐ Must Read: wakeupmh/optional handmade chaining - สรุปดราม่าล่าสุด

Does sounds like a charm or doesn't?

Top comments (7)

⭐ Must Read: wakeupmh/optional handmade chaining - สรุปดราม่าล่าสุด
 
felipperegazio profile image
Felippe Regazio • • Edited

Really cool solution, it does look like a charm : )
You can also extract the object value in a functional style with:

const optionalChaining = (obj, str) => (obj && str) && (() => str.split('.').reduce((o, i) => o[i], obj))();
⭐ Must Read: wakeupmh/optional handmade chaining - สรุปดราม่าล่าสุด ⭐ Must Read: wakeupmh/optional handmade chaining - สรุปดราม่าล่าสุด

and use like that:

const letters = { a: { b: 'c' } };

optionalChaining(letters, 'a'); // {b: "c"}
optionalChaining(letters, 'a.b'); // 'c'
optionalChaining(letters, 'a.b.e'); // undefined
optionalChaining(letters, 'z'); // undefined
⭐ Must Read: wakeupmh/optional handmade chaining - สรุปดราม่าล่าสุด ⭐ Must Read: wakeupmh/optional handmade chaining - สรุปดราม่าล่าสุด

We can also extend the Object prototype to avoid some problems (dont know about how good or bad it could be in terms of design, but its possible):

Object.prototype.optionalChaining = function (str) {
  return str.split('.').reduce((o, i) => o[i], this);
}

const letters = { a: { b: 'c' } };

letters.optionalChaining('a'); // {b: "c"}
letters.optionalChaining('a.b'); // 'c'
letters.optionalChaining('a.b.e'); // undefined
letters.optionalChaining('z'); // undefined
⭐ Must Read: wakeupmh/optional handmade chaining - สรุปดราม่าล่าสุด ⭐ Must Read: wakeupmh/optional handmade chaining - สรุปดราม่าล่าสุด
⭐ Must Read: wakeupmh/optional handmade chaining - สรุปดราม่าล่าสุด
 
wakeupmh profile image
Marcos Henrique •

Clean and beauty, thanks bro

⭐ Must Read: wakeupmh/optional handmade chaining - สรุปดราม่าล่าสุด
 
andrewbridge profile image
Andrew Bridge •

Always fun to work through these problems as a learning experience, but here's another implementation, based on the lodash get method.

github.com/cedmax/youmightnotneed/...

The same GitHub repo has examples of set and has implementations.

⭐ Must Read: wakeupmh/optional handmade chaining - สรุปดราม่าล่าสุด
 
wakeupmh profile image
Marcos Henrique •

Awesome tip fude, thank u for sharing 🌞🤘

⭐ Must Read: wakeupmh/optional handmade chaining - สรุปดราม่าล่าสุด
 
olavoparno profile image
Olavo Parno •

If Node's new stuff doesn't come to you, then move YOUR VERY SELF to Node's new stuff haha

⭐ Must Read: wakeupmh/optional handmade chaining - สรุปดราม่าล่าสุด
 
wakeupmh profile image
Marcos Henrique •

Suhsiajaidjdi it's ALL folks xD

⭐ Must Read: wakeupmh/optional handmade chaining - สรุปดราม่าล่าสุด
 
ecyrbe profile image
ecyrbe • • Edited

Here is another way based on proxy that that feels more native