How to Use Lodash _.unary with _.map
The Lodash _.unary method simplifies transforming
collections with _.map by restricting a target function to
accept only a single argument. When functions with optional
parameters—such as JavaScript's built-in parseInt—are
passed directly to _.map, unexpected behavior often occurs
because _.map supplies extra arguments like the current
index and the entire collection. By wrapping these callback functions in
_.unary, developers can prevent unwanted parameter passing,
avoid boilerplate arrow functions, and write cleaner, bug-free
functional code.
The Problem with Default Iteration Arguments
Both JavaScript's native Array.prototype.map and
Lodash's _.map pass three arguments to their iteratee
callback on each iteration:
value: The current element being processed.index: The index or key of the current element.collection: The entire array or object being traversed.
This design causes subtle bugs when passing a function that accepts
optional arguments. The most famous example is
parseInt(string, radix). When passed directly to
map:
['6', '8', '10'].map(parseInt);
// Output: [6, NaN, 2]The unexpected result happens because parseInt receives
the array index as its radix (base) parameter:
parseInt('6', 0)evaluates to6(radix 0 defaults to 10).parseInt('8', 1)evaluates toNaN(radix 1 is invalid).parseInt('10', 2)evaluates to2(radix 2 parses binary).
How _.unary Resolves
the Issue
The _.unary method creates a new function that caps the
arity (the number of accepted arguments) of the provided function to
exactly one. Any secondary or tertiary arguments supplied by
_.map are completely ignored.
const _ = require('lodash');
const safeParseInt = _.unary(parseInt);
_.map(['6', '8', '10'], safeParseInt);
// Output: [6, 8, 10]Under the hood, _.unary(fn) acts like a wrapper:
(arg) => fn(arg). When _.map calls the
wrapped function with ('8', 1, array), _.unary
discards 1 and array, forwarding only
'8' to parseInt.
Eliminating Boilerplate
Before _.unary, the standard workaround was manually
writing an anonymous function or arrow function to isolate the first
argument:
_.map(['6', '8', '10'], (num) => parseInt(num));While functional, this approach introduces boilerplate and manual
parameter naming. Using _.unary provides a point-free,
declarative alternative:
_.map(['6', '8', '10'], _.unary(parseInt));Key Takeaways
- Prevents Hidden Bugs: Ensures functions with optional secondary parameters do not mistakenly consume the iteration index or collection reference.
- Enables Point-Free Style: Allows developers to pass functions directly by reference without writing inline wrapper functions.
- Improves Readability: Clearly communicates the intent to treat the target function strictly as a single-argument transformation.