{"id":10799,"library":"es-toolkit","title":"ES-Toolkit","description":"ES-Toolkit is a modern, high-performance JavaScript utility library designed for both Node.js and browser environments, emphasizing a small bundle size and robust TypeScript type annotations. Currently at version 1.45.1, the library demonstrates an aggressive release cadence, with updates typically arriving monthly or bi-monthly, reflecting continuous development and refinement. Key differentiators include its focus on performance, minimal footprint, and comprehensive type definitions which make it an excellent choice for TypeScript projects. It offers a wide array of functions for array manipulation, object operations, asynchronous utilities, and more, often providing Lodash-like functionality with a modern, tree-shakable architecture. Recent updates have focused on refining type safety, enhancing compatibility with Lodash behaviors, and introducing async utility methods.","status":"active","version":"1.45.1","language":"javascript","source_language":"en","source_url":"https://github.com/toss/es-toolkit","tags":["javascript","typescript"],"install":[{"cmd":"npm install es-toolkit","lang":"bash","label":"npm"},{"cmd":"yarn add es-toolkit","lang":"bash","label":"yarn"},{"cmd":"pnpm add es-toolkit","lang":"bash","label":"pnpm"}],"dependencies":[],"imports":[{"note":"ES-Toolkit primarily uses named exports and is designed for ESM. While CommonJS might work in some bundlers, ESM imports are recommended for full tree-shaking and future compatibility.","wrong":"const { cloneDeep } = require('es-toolkit');","symbol":"cloneDeep","correct":"import { cloneDeep } from 'es-toolkit';"},{"note":"Individual functions are available via named exports from the main package. Direct subpath imports like 'es-toolkit/throttle' are not the primary recommended pattern and might lead to issues with certain bundlers or future updates.","wrong":"import throttle from 'es-toolkit/throttle';","symbol":"throttle","correct":"import { throttle } from 'es-toolkit';"},{"note":"For optimal tree-shaking and bundle size, always use named imports for specific utilities rather than importing the entire library as a namespace.","wrong":"import * as esToolkit from 'es-toolkit'; esToolkit.mapAsync(...);","symbol":"mapAsync","correct":"import { mapAsync } from 'es-toolkit';"}],"quickstart":{"code":"import {\n  cloneDeep,\n  isEmptyObject,\n  throttle,\n  mapAsync,\n  retry,\n} from 'es-toolkit';\n\ninterface User {\n  id: number;\n  name: string;\n  data?: Record<string, any>;\n}\n\nconst users: User[] = [\n  { id: 1, name: 'Alice', data: { age: 30 } },\n  { id: 2, name: 'Bob', data: {} },\n  { id: 3, name: 'Charlie' },\n];\n\n// Example 1: Deep cloning objects\nconst clonedUsers = cloneDeep(users);\nconsole.log('Cloned Users:', clonedUsers);\nconsole.log('Are they the same object reference?', clonedUsers === users); // false\n\n// Example 2: Checking for empty objects\nconst userWithEmptyData = users[1];\nconsole.log(`User ${userWithEmptyData.name} has empty data:`, isEmptyObject(userWithEmptyData.data));\n\n// Example 3: Throttling a function\nlet count = 0;\nconst throttledIncrement = throttle(() => {\n  count++;\n  console.log('Throttled increment called, count:', count);\n}, 100);\n\nthrottledIncrement();\nsetTimeout(throttledIncrement, 50); // Will not trigger\nsetTimeout(throttledIncrement, 150); // Will trigger again\n\n// Example 4: Asynchronous mapping\nconst fetchUserData = async (id: number) => {\n  await new Promise(resolve => setTimeout(resolve, 50 * id)); // Simulate async\n  return { id, status: 'fetched' };\n};\n\n(async () => {\n  const userStatuses = await mapAsync(users, async (user) => {\n    return fetchUserData(user.id);\n  });\n  console.log('User statuses:', userStatuses);\n})();\n\n// Example 5: Retrying a failing operation\nlet attempt = 0;\nconst flakyOperation = async () => {\n  attempt++;\n  if (attempt < 3) {\n    console.log(`Flaky operation attempt ${attempt}: Failing...`);\n    throw new Error('Transient error');\n  }\n  console.log(`Flaky operation attempt ${attempt}: Succeeded!`);\n  return 'Success';\n};\n\n(async () => {\n  try {\n    const result = await retry(flakyOperation, { retries: 5, delay: 100 });\n    console.log('Retry result:', result);\n  } catch (e) {\n    console.error('Retry failed:', (e as Error).message);\n  }\n})();","lang":"typescript","description":"Demonstrates core utility functions like deep cloning, object emptiness checks, throttling, asynchronous mapping, and retrying operations, highlighting its modern API and TypeScript compatibility."},"warnings":[{"fix":"Review calls to `sample` and ensure type assertions or nullish checks are appropriate for a return type that *does not* include `undefined` (as of v1.45.1 and earlier versions).","message":"The return type of the `sample` function was changed in v1.45.0 to include `undefined`, but subsequently reverted in v1.45.1. Users who adapted their TypeScript code to handle `undefined` in v1.45.0 might experience type errors or runtime issues after upgrading to v1.45.1 or later.","severity":"breaking","affected_versions":"==1.45.0"},{"fix":"Test `merge` functionality thoroughly after upgrading to v1.43.0 or later, especially with complex nested objects, arrays, and special value types like `Date`.","message":"The `merge` function's behavior was enhanced in v1.43.0 to handle arrays and objects more consistently and to match Lodash's behavior with date values and array-like objects. This change could lead to different merging outcomes compared to previous versions if your application relied on the older, non-Lodash compatible behavior.","severity":"breaking","affected_versions":"<1.43.0"},{"fix":"Upgrade to v1.43.0 or later to get the correct `throttle` behavior. Review any existing `throttle` implementations to ensure they now function as intended after the fix.","message":"Prior to v1.43.0, the `throttle` function had a bug where it behaved like `debounce`. If you were using `throttle` in affected versions, its behavior might have been significantly different from the expected throttling mechanism.","severity":"gotcha","affected_versions":"<1.43.0"},{"fix":"Verify usages of `omit` on array-like objects after upgrading to v1.42.0. Ensure your code does not depend on `omit` modifying array-like objects in unexpected ways.","message":"The `omit` function was fixed in v1.42.0 to prevent adding index properties to array-like objects. While a fix, this change in behavior could be considered breaking if your code implicitly relied on the previous, incorrect modification of array-like objects.","severity":"breaking","affected_versions":"<1.42.0"},{"fix":"If using `defaultsDeep` with arrays containing objects, upgrade to v1.39.10 or later and re-test to ensure merging occurs as expected.","message":"The `defaultsDeep` function received a fix in v1.39.10 to properly handle deep merging of objects within arrays. Previous versions might have exhibited incorrect or unexpected merging behavior when dealing with nested objects inside array structures.","severity":"gotcha","affected_versions":"<1.39.10"}],"env_vars":null,"last_verified":"2026-04-19T00:00:00.000Z","next_check":"2026-07-18T00:00:00.000Z","problems":[{"fix":"Ensure you are using `import { someFunction } from 'es-toolkit';` for ESM environments. Verify the specific function exists in your installed version. Prior to v1.45.0, some packages might have been missing from `publishConfig`, leading to module not found errors for specific utilities.","cause":"Attempting to use CommonJS `require()` or incorrect named imports in an environment expecting ESM, or a specific utility was not correctly exported in a prior version.","error":"TypeError: (0 , es_toolkit__WEBPACK_IMPORTED_MODULE_0__.someFunction) is not a function"},{"fix":"Check the exact version of `es-toolkit` you are using. For `sample`, ensure you are on v1.45.1+ if you expect no `undefined` in the return type. Always add appropriate nullish checks or type guards when dealing with potentially optional return values.","cause":"This error can occur in TypeScript, specifically for versions <1.45.0 where `sample` might have returned `undefined` in its type signature, but then was reverted in v1.45.1. Or, it indicates a general type mismatch where a function's return type no longer includes a type you're expecting.","error":"Property 'x' does not exist on type 'T'. Property 'x' does not exist on type 'undefined'."},{"fix":"Review the function signature in the ES-Toolkit documentation or your IDE's type hints. Ensure your input types align with the expected parameters. You might need to refine your own types, use type assertions (`as`), or provide explicit type arguments if the function is generic.","cause":"A common TypeScript error indicating that the types inferred or provided to an ES-Toolkit utility function do not match its expected parameters, often due to strict type checking or changes in the library's type definitions.","error":"Argument of type 'T' is not assignable to parameter of type 'U'."},{"fix":"For Node.js, ensure your `package.json` has `\"type\": \"module\"` or use a `.mjs` file extension. For older environments, consider using a bundler (like Webpack, Rollup, Parcel) to transpile your code to a compatible format.","cause":"Attempting to use ESM `import` syntax in a Node.js environment configured for CommonJS, or in an older browser environment without a module loader.","error":"SyntaxError: Cannot use import statement outside a module"}],"ecosystem":"npm"}