0

In Typescript (and Javascript for that matter), you can access an object's properties using the dot notation or the bracket notation:

object.property
object['property']

Using a concrete example for the latter:

const user = {
    firstName: 'John',
    lastName: 'Doe'
}
const prop = 'firstName';
console.log(user[prop]);  //"John"

My question is if/how bracket notation can be used for array properties where the value in the bracket is a path to an array. Here is an example:

const user = {
    firstName: 'John',
    lastName: 'Doe',
    nicknames: [
        { id: 1, value: 'Johnny'}, 
        { id: 2, value: 'JD'}, 
        { id: 3, value: 'Dude'}
    ]
}
const prop = 'nicknames[2].value';
console.log(user[prop]);

My goal with the console.log() would be to print JD, but this example would fail because there is, of course, no property of user called nicknames[2].value;

How can I use bracket notation in this manner with array properties?

mellis481
  • 4,332
  • 12
  • 71
  • 118
  • 1
    Have a look at lodash's get function: https://lodash.com/docs/4.17.4#get – JanS Dec 07 '17 at 16:44
  • You could use `eval` eg: `console.log(eval("user." + prop));` or create a function that parses the string to extract the property names and indexes. – Titus Dec 07 '17 at 16:44
  • If you are expecting JD then you are also suggesting that nicknames[2] is actually the element where the object's id = 2. nicknames[2] actually points to { id: 3, value: 'Dude'}. – John Dec 07 '17 at 16:48
  • @JanS `get()` FTW! Thanks – mellis481 Dec 07 '17 at 16:48

2 Answers2

2

If you do not fancy including lodash for a single function then you might consider adding a function onto your object which provides this functionality.

I have provided a snippet with an example which is able to use the type of prop string that you specified in your question

const user = {
    firstName: 'John',
    lastName: 'Doe',
    nicknames: [
        { id: 1, value: 'Johnny'}, 
        { id: 2, value: 'JD'}, 
        { id: 3, value: 'Dude'}
    ],
    byProp (path) {
      return path.split(/\].|\]\[|\[|\./) // split on [] or .
                 .map( el => el.replace(/\]$/,'')) // remove any trailing ']'
                 // loop over split-string to get element
                 // return undefined if the property does not exist
                 .reduce( (obj, el) => obj? obj[el]:undefined, this);
    }
}

console.log(user.byProp('nicknames[2].value'));
console.log(user.byProp('nicknames[1][value]'));
console.log(user.byProp('firstName'));
console.log(user.byProp('firstName.undefined'));
John
  • 1,313
  • 9
  • 21
1

Based on @JanS's suggestion, I was able to accomplish what I needed with the following use of lodash's get() method:

const prop = 'nicknames[2].value';
console.log(_.get(user, prop));
mellis481
  • 4,332
  • 12
  • 71
  • 118