Lodash sumBy String Concatenation on Nested Keys

While the Lodash _.sumBy function is primarily intended to compute numerical sums across collections, passing a string path pointing to nested string values causes it to return a concatenated string instead of a number. This behavior is the direct result of how Lodash resolves nested object paths combined with the implicit type coercion rules of JavaScript's addition operator (+) within its internal iteration loop.

When invoking _.sumBy(collection, 'deeply.nested.property'), Lodash first transforms the string path into an iteratee function. Internally, Lodash delegates this to baseIteratee, which creates a property accessor via basePropertyDeep and baseGet. As Lodash iterates over the collection, it traverses each object along the dot-notation path, safely extracting the deeply nested value even if intermediate parent keys are missing.

Once the nested value is extracted, execution shifts to Lodash's internal baseSum algorithm. The implementation of baseSum follows a straightforward accumulator pattern:

function baseSum(array, iteratee) {
  var result,
      index = -1,
      length = array.length;

  while (++index < length) {
    var current = iteratee(array[index]);
    if (current !== undefined) {
      result = result === undefined ? current : (result + current);
    }
  }
  return result;
}

The string concatenation occurs because of two key steps inside this loop:

  1. Accumulator Initialization: The variable result begins as undefined. On the first iteration where the nested lookup returns a valid (non-undefined) string, the ternary condition result === undefined ? current : (result + current) assigns that initial string directly to result.
  2. Evaluation via the + Operator: On subsequent iterations, result already holds a string primitive. When the loop executes result + current, the native JavaScript addition operator encounters at least one string operand. Rather than performing mathematical addition, JavaScript defaults to string concatenation, joining the values sequentially.

Because baseSum does not validate that current is a number, nor does it convert inputs via Number() or parseFloat(), the accumulation purely reflects native JavaScript coercion. If intermediate properties are undefined, they are skipped; however, if deeply nested properties resolve to null, numbers, or booleans in a mixed collection, JavaScript coerces those values into string representations during the addition phase (for example, "text" + null becomes "textnull").