1

Is there a better way to handle null values within the example below. In entries 5, 7, and 10; a null value is present.

The following errors are presented whether the value is null or undefined.

#5  - Uncaught TypeError: Cannot read property 'id' of null
#7  - Uncaught TypeError: object null is not iterable (cannot read property Symbol(Symbol.iterator))
#10 - Uncaught TypeError: Cannot read property 'id' of null

const data = [
  { id: 1, children: [{ id: 'A' }] }, /*  1 */
  { id: 2, children: [{ id: 'B' }] }, /*  2 */
  { id: 3, children: [{ id: 'C' }] }, /*  3 */
  { id: 4, children: [{ }] },         /*  4 */
  //{ id: 5, children: [null] },      /*  5 */
  { id: 6, children: [] },            /*  6 */
  //{ id: 7, children: null },        /*  7 */
  { id: 8 },                          /*  8 */
  { },                                /*  9 */
  //null                              /* 10 */
];

const ids = data.map(
  ({
    id = -1,
    children: [
      {
        id: childId = -1
      } = {}
    ] = []
  } = {}) =>
    ({ id, childId })
);

console.log(ids);
.as-console-wrapper { top: 0; max-height: 100% !important; }

The following works, but it is less elegant. It requires the use of nullish-coalescing operators (or logical OR operators), optional chaining, and multiple assignments.

const data = [
  { id: 1, children: [{ id: 'A' }] }, /*  1 */
  { id: 2, children: [{ id: 'B' }] }, /*  2 */
  { id: 3, children: [{ id: 'C' }] }, /*  3 */
  { id: 4, children: [{}] },          /*  4 */
  { id: 5, children: [null] },        /*  5 */
  { id: 6, children: [] },            /*  6 */
  { id: 7, children: null },          /*  7 */
  { id: 8 },                          /*  8 */
  { },                                /*  9 */
  null                                /* 10 */
];

const ids = data.map(item => {
  const
    ref = item ?? {},
    children = ref.children ?? [],
    child = children[0] ?? {};
  return {
    id: ref?.id ?? -1,
    childId: child?.id ?? -1
  };
});

console.log(ids);
.as-console-wrapper { top: 0; max-height: 100% !important; }

I could rewrite this as a nested IIFE, but it is more difficult to follow... As you can see, I avoided using default parameter values, because you can only destructure undefined values. The value null is valid, so I have to use a logical OR (a nullish-coalescing operation would work too) to determine the alternative.

const data = [
  { id: 1, children: [{ id: 'A' }] },  /*  1       */
  { id: 2, children: [{ id: 'B' }] },  /*  2       */
  { id: 3, children: [{ id: 'C' }] },  /*  3       */
  { id: 4, children: [{ id: null }] }, /*  4 (NEW) */
  { id: 5, children: [{}] },           /*  5       */
  { id: 6, children: [null] },         /*  6       */
  { id: 7, children: [] },             /*  7       */
  { id: 8, children: null },           /*  8       */
  { id: 9 },                           /*  9       */
  { },                                 /* 10       */
  null                                 /* 11       */
];

const ids = data.map(item =>
  (ref =>
    ((id, children) =>
      (child =>
        ((childId) =>
          ({ id, childId }))
        (child.id || -1))
      (children[0] || {}))
    (ref.id || -1, ref.children || []))
  (item || {}));

console.log(ids);
.as-console-wrapper { top: 0; max-height: 100% !important; }

1 Answer 1

2

You could do away with the multiple assignments. I don't see any issues with using nullish coalescing and optional chaining.

const data = [
  { id: 1, children: [{ id: 'A' }] },  /*  1       */
  { id: 2, children: [{ id: 'B' }] },  /*  2       */
  { id: 3, children: [{ id: 'C' }] },  /*  3       */
  { id: 4, children: [{ id: null }] }, /*  4 (NEW) */
  { id: 5, children: [{}] },           /*  5       */
  { id: 6, children: [null] },         /*  6       */
  { id: 7, children: [] },             /*  7       */
  { id: 8, children: null },           /*  8       */
  { id: 9 },                           /*  9       */
  { },                                 /* 10       */
  null                                 /* 11       */
];

const ids = data.map(item => ({
    id: item?.id ?? -1,
    childId: item?.children?.[0]?.id ?? -1
}));

console.log(ids);
.as-console-wrapper { top: 0; max-height: 100% !important; }

Sign up to request clarification or add additional context in comments.

1 Comment

Could be me, but I think this is actually a lot more readable than any of the variants in the question

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.