How to Use Lodash in TypeScript with @types/lodash

Integrating Lodash into a TypeScript project allows developers to combine Lodash's powerful collection of utility functions with TypeScript’s static type-checking and autocompletion. Because Lodash is originally authored in JavaScript, it does not include built-in type declarations in its primary package. This integration is bridged using the @types/lodash community package from DefinitelyTyped, which supplies ambient type definitions to the TypeScript compiler, ensuring full type safety across your codebase.

Why @types/lodash Is Necessary

Lodash provides hundreds of utility functions for manipulating arrays, objects, strings, and other data structures. However, the standard lodash package contains only JavaScript code.

When you import lodash into a TypeScript project without type definitions, the compiler cannot verify function signatures, parameter types, or return values, resulting in an implicit any error or missing type information. The @types/lodash package contains .d.ts (declaration) files that map out the types for every Lodash function, enabling:

Installation

To integrate Lodash with TypeScript, install both the core library as a runtime dependency and its corresponding type definitions as a development dependency.

Using npm:

npm install lodash
npm install -D @types/lodash

Using Yarn:

yarn add lodash
yarn add -D @types/lodash

Using pnpm:

pnpm add lodash
pnpm add -D @types/lodash

TypeScript Configuration (tsconfig.json)

To ensure smooth imports, your tsconfig.json should have esModuleInterop set to true. This allows CommonJS modules like Lodash to be imported similarly to ES modules.

{
  "compilerOptions": {
    "target": "ES2020",
    "module": "commonjs",
    "moduleResolution": "node",
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true
  }
}

Importing and Using Lodash with Types

There are several ways to import Lodash, each affecting bundle size and how types are resolved.

1. Global Import

You can import the entire library under the standard _ identifier:

import _ from 'lodash';

interface User {
  id: number;
  name: string;
  active: boolean;
}

const users: User[] = [
  { id: 1, name: 'Alice', active: true },
  { id: 2, name: 'Bob', active: false },
];

// TypeScript correctly infers 'activeUsers' as User[]
const activeUsers = _.filter(users, { active: true });

2. Named Imports

You can import specific functions to keep code explicit:

import { chunk, cloneDeep } from 'lodash';

const numbers: number[] = [1, 2, 3, 4, 5];
const chunked: number[][] = chunk(numbers, 2);

Note: Depending on your bundler (like Webpack or Vite), named imports from 'lodash' may still bundle the entire library unless tree-shaking plugins are configured.

3. Per-Method Imports (Optimal for Bundling)

For maximum optimization in production builds, you can import specific submodules:

import debounce from 'lodash/debounce';

const handleResize = debounce((event: Event) => {
  console.log('Window resized', event);
}, 200);

The @types/lodash package automatically maps types to these individual path imports, ensuring full type safety without requiring you to install separate packages like @types/lodash.debounce.

Type Safety Benefits

With @types/lodash, Lodash functions adapt to your custom types via TypeScript generics. For example, methods such as _.keyBy, _.groupBy, and _.map maintain strong typing throughout transformations:

interface Product {
  sku: string;
  price: number;
}

const inventory: Product[] = [
  { sku: 'A1', price: 10 },
  { sku: 'B2', price: 25 },
];

// 'catalog' is automatically typed as Record<string, Product | undefined>
const catalog = _.keyBy(inventory, 'sku');

By adding @types/lodash alongside lodash, you get seamless integration that combines runtime reliability with compile-time safety.