How Lodash _.transform Infers Accumulator Type

The Lodash _.transform method provides an ergonomic alternative to _.reduce, allowing developers to iterate over collections and mutate an accumulator directly without explicitly returning it in each cycle. When the accumulator argument is omitted, Lodash automatically determines its initial type by inspecting the constructor, prototype, and underlying data structure of the source collection, defaulting to a new instance that mirrors the original target.

The Accumulator Resolution Strategy

When you invoke _.transform(collection, iteratee) without passing a third argument, Lodash determines the initial accumulator using the following resolution hierarchy:

1. Arrays and Array-Like Structures

If the input collection is an Array, Lodash creates a new instance using the source array's constructor (new object.constructor or a fresh []). For other array-like structures, such as typed arrays or Buffers, Lodash defaults to an empty standard array ([]) to avoid unintended memory or buffer-size constraints during mutation.

const sourceArray = [1, 2, 3];
const result = _.transform(sourceArray, (acc, val) => {
  acc.push(val * 2);
});

console.log(Array.isArray(result)); // true
console.log(result); // [2, 4, 6]

2. Objects and Custom Prototypes

If the collection is an object, Lodash attempts to preserve its prototype chain. Rather than simply instantiating a plain {} literal:

This prototype inheritance ensures that custom class instances transformed via _.transform retain their inherited methods on the resulting accumulator:

class BaseConfig {
  isValid() {
    return true;
  }
}

const configInstance = Object.assign(new BaseConfig(), { a: 1, b: 2 });

const transformed = _.transform(configInstance, (acc, val, key) => {
  acc[key] = val * 10;
});

console.log(transformed instanceof BaseConfig); // true
console.log(transformed.isValid()); // true

3. Primitives and Fallbacks

If the target passed to _.transform is neither an array-like entity nor a standard object (such as null, undefined, or primitive values), Lodash initializes the accumulator as a fresh, empty object ({}).

Why the Default Inference Matters

By automatically checking constructor properties and the prototype chain, _.transform eliminates boilerplate code. Developers do not need to manually pass [] when transforming arrays or worry about losing prototype methods when working with instances of custom classes. If a transformation requires a distinct target type—such as converting an object's key-value pairs into an array—an explicit accumulator must still be provided as the third parameter.