lodash, ramda, remeda, and underscore are utility libraries that provide helper functions for common programming tasks like array manipulation, object handling, and function composition. lodash is the industry standard with a massive API surface. ramda focuses on functional programming with automatic currying and immutable data. remeda is a modern alternative designed for TypeScript and tree-shaking. underscore is the original library that inspired lodash, now mostly used for legacy support.
When building JavaScript applications, you often need to transform data, filter lists, or manage object properties. The lodash, ramda, remeda, and underscore libraries provide tested utilities for these tasks, but they differ in style, type safety, and bundle impact. Let's compare how they handle common engineering challenges.
lodash and underscore use an object-first approach.
// lodash: Data is the first argument
import _ from 'lodash';
const result = _.map([1, 2, 3], (n) => n * 2);
// underscore: Similar object-first style
import _ from 'underscore';
const result = _.map([1, 2, 3], (n) => n * 2);
ramda and remeda use a data-last approach.
// ramda: Data is the last argument (curried)
import { map } from 'ramda';
const double = map((n) => n * 2);
const result = double([1, 2, 3]);
// remeda: Data is the last argument (functional)
import { map } from 'remeda';
const result = map([1, 2, 3], (n) => n * 2);
Type safety is critical in modern frontend development. The libraries differ in how well they support TypeScript inference.
lodash has type definitions, but they can be loose.
// lodash: Types may require casting
import _ from 'lodash';
const users = [{ id: 1 }];
// TypeScript might infer 'any' without extra care
const ids = _.map(users, (u) => u.id);
ramda has strong types but can be verbose.
// ramda: Strong but complex types
import { map } from 'ramda';
// Type inference works but error messages can be long
const double = map((n: number) => n * 2);
remeda is built for TypeScript first.
// remeda: Clean type inference
import { map, pipe } from 'remeda';
// Types flow naturally through the pipe
const result = pipe(
[1, 2, 3],
map((n) => n * 2)
);
underscore has older type definitions.
@types/underscore which are less maintained.// underscore: Legacy types
import _ from 'underscore';
// Basic types, less inference help
const result = _.map([1, 2, 3], (n) => n * 2);
Bundle size affects load times. How you import these libraries matters.
lodash is large if imported fully.
import map from 'lodash/map'.// lodash: Modular import required for small bundles
import map from 'lodash/map';
// Without this, you might bundle the whole library
ramda is hard to tree-shake.
// ramda: Named imports but tree-shaking is limited
import { map, filter } from 'ramda';
// Bundlers may struggle to remove unused parts
remeda is designed for tree-shaking.
// remeda: Optimized for tree-shaking
import { map, filter } from 'remeda';
// Unused functions are reliably dropped from the bundle
underscore is a single monolithic file.
// underscore: Monolithic import
import _ from 'underscore';
// Entire library is included in the bundle
Choosing a library means trusting its maintainers.
lodash is stable and widely used.
ramda is stable with a dedicated community.
remeda is actively developed.
underscore is in maintenance mode.
| Feature | lodash | ramda | remeda | underscore |
|---|---|---|---|---|
| Style | π§± Object-first | π§ͺ Functional (Curried) | π§ͺ Functional (Data-last) | π§± Object-first |
| TypeScript | β οΈ Good but loose | β Strong but complex | β Excellent inference | β οΈ Legacy types |
| Tree Shaking | β οΈ Manual modular imports | β Hard to shake | β Built for shaking | β Monolithic |
| Status | π’ Stable Standard | π’ Stable FP | π’ Active Modern | π‘ Legacy / Maintenance |
lodash is the safe choice π‘οΈ for teams that want a vast API and don't want to debate style. It works everywhere and is well understood.
ramda is the functional choice π§ͺ for teams committed to immutability and composition. It requires a shift in thinking but offers powerful tools.
remeda is the modern choice π for TypeScript projects. It gives you functional benefits without the bundle bloat or type headaches.
underscore is the legacy choice π°οΈ. Avoid it for new work unless you are tied to an older stack.
Final Thought: For most new frontend projects, remeda offers the best balance of modern features and performance. If you need maximum compatibility and a huge API, lodash remains the king. Choose based on your team's comfort with functional style and your bundle constraints.
Choose lodash if you need a comprehensive set of utilities that work consistently across different environments. It is ideal for large teams where standardization is key and bundle size is less of a concern due to its modular import options.
Choose ramda if your team embraces functional programming principles and wants automatic currying for function composition. It is suitable for projects that prioritize immutable data flows and point-free style coding.
Choose remeda if you are building a TypeScript-heavy application and care about bundle size. It offers the functional style of ramda but with better tree-shaking support and simpler type inference.
Choose underscore only if you are maintaining an older codebase that already depends on it. For new projects, it is better to evaluate modern alternatives due to slower update cycles and lack of modern features.
The Lodash library exported as Node.js modules.
Using npm:
$ npm i -g npm
$ npm i --save lodash
In Node.js:
// Load the full build.
var _ = require('lodash');
// Load the core build.
var _ = require('lodash/core');
// Load the FP build for immutable auto-curried iteratee-first data-last methods.
var fp = require('lodash/fp');
// Load method categories.
var array = require('lodash/array');
var object = require('lodash/fp/object');
// Cherry-pick methods for smaller browserify/rollup/webpack bundles.
var at = require('lodash/at');
var curryN = require('lodash/fp/curryN');
See the package source for more details.
Note:
Install n_ for Lodash use in the Node.js < 6 REPL.
Tested in Chrome 74-75, Firefox 66-67, IE 11, Edge 18, Safari 11-12, & Node.js 8-12.
Automated browser & CI test runs are available.