Getting and checking value from a mixed object array HTTP endpoint I try to get location data by a external HTTP call. For this API, any part in the data can be missing. Initially I wrote the following code to check whether data.res.accounts[0].contacts[0].location exists:
const getLocation = async () =&gt; {
  const data = await fetchLocation();
  if (
    data == null
    data.res == null ||
    data.res.accounts == null ||
    data.res.accounts[0] == null ||
    data.res.accounts[0].contacts == null ||
    data.res.accounts[0].contacts[0] == null ||
    data.res.accounts[0].contacts[0].location == null
  ) {
    return null;
  }
  return data.res.accounts[0].contacts[0].location;
}

I have tried to simplify the mixed object and array code.
One way of doing this is using JavaScript's new conditional operator ?..
For example if they are all objects then I can use something like:
if (data?.res?.account?.contact?.location == null) {
  return null;
}

However my data is mixed with arrays and objects. This is the best I've come up with:
if (
  data?.res?.accounts == null ||
  data.res.accounts[0]?.contacts == null ||
  data.res.accounts[0].contacts[0]?.location == null
) {
  return null;
}

Can I simplify it further?
Optional chaining can be used not only with object property lookup with dot notation, but also with bracket notation, by putting ?. before the [:


const data = { res: {}};
console.log(data?.res?.accounts?.[0]?.contacts?.[0]?.location == null)



Just to be thorough, you can also use optional chaining with function calls:


const data = { res: { }};
console.log(data?.res?.accounts?.[0]?.contacts?.[0].location?.includes?.('foobar'));

const data2 = { res: { accounts: [{ contacts: [{ location: 'foobarbaz' }] }] } };
console.log(data2?.res?.accounts?.[0]?.contacts?.[0].location?.includes?.('foobar'));

const data3 = { res: { accounts: [{ contacts: [{ location: 7 }] }] } };
console.log(data3?.res?.accounts?.[0]?.contacts?.[0].location?.includes?.('foobar'));



That said, having so many nested properties whose existence is uncertain is a bit of a code smell, because any time you want to look something up, you'll have to check the existence of all intermediate properties first. Despite the fact that you can do it concisely with optional chaining nowadays, it's quite a strange data structure. If you have control over fetchLocation, consider if you can refactor it so that fewer intermediate properties may be missing. (For example, if you could change it so that every account has a contacts array, and the array might be empty (but not null nor undefined), that'd be a step in the right direction).
Also, keep in mind that optional chaining is extremely new syntax. If this is going to be running on a public website, make sure to transpile your code down to ES6 or ES5 for production so that those with older browsers can consume your code.
On another note, you might consider using === instead of ==. ESLint rule: eqeqeq. == has some pretty odd behaviors involving type coercion that developers shouldn't be forced to look up in order to be 100% confident of what logic a particular section of code is implementing. For example, you could use ?? instead, to handle cases of undefined or null:
const location = data?.res?.accounts?.[0]?.contacts?.[0]?.location;
return location ?? null;

(Or, if location will always be a non-empty string, you could return location || null, which might be a bit better)
Also, the conditional operator is not in any of the code in your question or this answer. The conditional operator uses syntax of the form:
const resultingExpression = condition ? expression1 : expression2;