function synthesizeItemKeyDiffs(diffs, baseItems, compareItems) {
  /** @type {Array<LHCI.AuditDiff>} */
  const itemKeyDiffs = [];

  for (const diff of diffs) {
    if (diff.type !== 'itemAddition' && diff.type !== 'itemRemoval') continue;

    const item =
      diff.type === 'itemAddition'
        ? compareItems[diff.compareItemIndex]
        : baseItems[diff.baseItemIndex];

    for (const key of Object.keys(item)) {
      const baseValue = diff.type === 'itemAddition' ? 0 : item[key];
      const compareValue = diff.type === 'itemAddition' ? item[key] : 0;
      if (typeof compareValue !== 'number' || typeof baseValue !== 'number') continue;

      const itemIndexKeyName = diff.type === 'itemAddition' ? 'compareItemIndex' : 'baseItemIndex';
      const itemIndexValue =
        diff.type === 'itemAddition' ? diff.compareItemIndex : diff.baseItemIndex;
      itemKeyDiffs.push(
        createAuditDiff({
          auditId: diff.auditId,
          type: 'itemDelta',
          itemKey: key,
          [itemIndexKeyName]: itemIndexValue,
          baseValue,
          compareValue,
        })
      );
    }
  }

  return itemKeyDiffs;
}
This function creates NumericItemAuditDiffs from itemAddition/itemRemoved diffs. Normally, these
are superfluous data, but in some instances (table details views for example), it's desirable to
understand the diff state of each individual itemKey. The missing values are assumed to be 0
for the purposes of the diff.

@param {Array<LHCI.AuditDiff>} diffs
@param {Array<Record<string, any>>} baseItems
@param {Array<Record<string, any>>} compareItems
@return {Array<LHCI.AuditDiff>}