Install and Use @types Packages

Learn how to find, install, and use @types packages to add type definitions for JavaScript libraries in your TypeScript project.

6 min read

When you install a JavaScript library like lodash, express, or react, the actual code on disk is plain JavaScript. TypeScript needs type definitions to give you autocomplete, parameter checking, and inline errors for that library.

@types packages provide those definitions. They are community-maintained declaration files published under the @types scope on npm. Installing one takes a single command, and TypeScript discovers it automatically.

What @types Packages Contain

An @types package ships only declaration files, no JavaScript, no runtime code. When you install @types/lodash, you get a small tree of declaration files like this.

texttext
node_modules/@types/lodash/
  index.d.ts
  common/
    array.d.ts
    collection.d.ts

These files describe every function, parameter, and return type in lodash. TypeScript reads them during compilation and uses them to check your code. The files are erased during compilation and never appear in your output bundle.

Step 1: Check If the Library Already Has Types

Before reaching for @types, check whether the library bundles its own type definitions. Many modern packages ship types directly:

bashbash
npm info express types

If this returns a file path like ./index.d.ts, the package includes its own types and you do not need @types/express.

You can also look inside the package's node_modules folder for declaration files, or check its package.json for a types or typings field. If none of these exist, proceed to @types.

Step 2: Install the @types Package

Install the type definitions as a dev dependency:

bashbash
npm install --save-dev @types/lodash

Once installed, TypeScript automatically discovers the types without any configuration change. You can immediately use the library with full type support, including autocomplete and argument checking on every call.

typescripttypescript
import _ from "lodash";
 
const padded = _.padStart("Hello", 20, " ");
//    ^ string -- TypeScript knows the return type
 
const result = _.padStart(42, 20, " ");
//                        ^^
// Argument of type 'number' is not assignable to parameter of type 'string'.

No extra configuration is needed. TypeScript scans node_modules/@types by default and picks up the declarations.

How TypeScript Discovers @types

TypeScript automatically includes every package under the typeRoots compiler option during compilation, with no import needed. The default typeRoots includes node_modules/@types:

jsonjson
{
  "compilerOptions": {
    "typeRoots": ["./node_modules/@types"]
  }
}

When TypeScript encounters an import from "lodash", it checks three places in order, stopping at the first match it finds. The table below shows that lookup order.

OrderWhere TypeScript looks
1Types bundled with the lodash package itself
2A matching @types/lodash package in node_modules/@types
3Any custom typeRoots folders you have configured

You can add your own folders to typeRoots for project-specific declarations:

jsonjson
{
  "compilerOptions": {
    "typeRoots": ["./node_modules/@types", "./src/types"]
  }
}

With this configuration, TypeScript also reads declaration files from src/types/. This is useful for typing untyped packages that have no community types.

The types Compiler Option

The types option controls which @types packages are automatically included. Without it, all @types packages in typeRoots are visible:

jsonjson
{
  "compilerOptions": {
    "types": ["node", "jest"]
  }
}

With "types": ["node", "jest"], only @types/node and @types/jest are automatically included. All other @types packages in node_modules are ignored unless explicitly imported.

This is useful when you want strict control over the global type environment, for example, preventing test types from leaking into your application code.

Installing the Library and Its Types Together

The library and its types are separate packages. You need both:

bashbash
npm install lodash                  # Runtime code
npm install --save-dev @types/lodash  # Type definitions only

If you forget the @types package, TypeScript shows a compiler error the moment you try to import the library, rather than letting the import through untyped.

texttext
Could not find a declaration file for module 'lodash'.
  Try `npm install --save-dev @types/lodash` if it exists
  or add a new declaration (.d.ts) file containing `declare module 'lodash';`

The error message tells you exactly what to do. Run the suggested command, and the error disappears.

Common Patterns for Different Package Types

Not all packages follow the same naming. Here is how to find types for common scenarios:

PackageType packageNotes
lodash@types/lodashStandard pattern
express@types/expressStandard pattern
react@types/reactStill a separate package, not bundled with react
date-fns(bundled)Ships its own types, no @types package needed
jest@types/jestTesting frameworks use @types
node@types/nodeNode.js built-in APIs need @types/node
Scoped: @scope/pkg@types/scope__pkgDouble underscore replaces slash

For scoped packages, the slash is replaced with a double underscore. For example, @babel/core becomes @types/babel__core.

What to Do When @types Does Not Exist

If you run npm install --save-dev @types/some-package and get a 404, the community has not yet typed that package. You have two options:

  1. Quick shim: Create a minimal declaration that tells TypeScript the module exists, silencing the error while treating every import from it as any.
typescripttypescript
// types/some-package.d.ts
declare module "some-package";
  1. Write real types: Create a full declaration file describing the parts of the API you actually use, using the same declare module pattern covered in ambient declarations in TypeScript.

Keeping @types Up to Date

@types packages are versioned separately from the libraries they describe. It is possible for the types to drift from the actual library API.

Run npm outdated periodically to see if newer versions of @types packages are available. The command lists every dependency where the installed version trails the latest published release.

bashbash
npm outdated

The output shows the currently installed version next to the latest one, so you can see at a glance which type packages have fallen behind.

texttext
Package          Current  Wanted  Latest
@types/lodash    4.14.0   4.14.1  4.14.2

Update them like any other dev dependency, using the @latest tag to jump straight to the newest published version instead of manually editing the version number in package.json.

bashbash
npm install --save-dev @types/lodash@latest

If a library has a major version bump, check whether its @types counterpart also has a corresponding major version. The @types package version typically mirrors the library's major and minor version.

Rune AI

Rune AI

Key Insights

  • Install @types packages with npm install --save-dev @types/package-name.
  • Always install @types as devDependencies, never as production dependencies.
  • TypeScript automatically discovers types in node_modules/@types.
  • Many popular packages now bundle their own types, making @types unnecessary.
  • Use typeRoots in tsconfig.json to add custom type declaration folders.
RunePowered by Rune AI

Frequently Asked Questions

What is the difference between a package and its @types counterpart?

The main package contains the runtime JavaScript code. The @types package contains only type definitions (.d.ts files). Installing @types/lodash adds types so TypeScript can check your usage of lodash, but it does not install lodash itself.

Do I install @types as a dependency or devDependency?

Always install @types packages as devDependencies. Type definitions are only needed during development and compilation. They produce no runtime code and are not required in production.

What if no @types package exists for the library I need?

You can create your own declaration file using declare module. See the article on typing untyped packages for a step-by-step guide.

Conclusion

@types packages are the easiest way to add type safety to JavaScript dependencies. The workflow is simple: install the library, install its @types counterpart as a devDependency, and start coding with full autocomplete and type checking. TypeScript discovers them automatically through node_modules/@types and typeRoots.