typescriptseverity: can-fix
TS2307

TypeScript TS2307: Cannot find module 'X' or its corresponding type declarations

Cannot find module

95% fixable~5 mindifficulty: beginner

Verified against TypeScript docs: Module Resolution, TypeScript handbook: Modules, TypeScript 5.5 release notes · Updated June 2026

> quick_fix

TypeScript can't find the module you're importing. Either the package isn't installed, the type declarations are missing, or the import path is wrong. Run npm install for the package, install @types/packagename if types are separate, or check your tsconfig.json moduleResolution setting.

// TS2307: Cannot find module 'lodash' or its corresponding type declarations
import _ from 'lodash'

// Fix 1: install the package
// npm install lodash

// Fix 2: install type declarations
// npm install -D @types/lodash

// Fix 3: if no types exist, declare the module
// In a .d.ts file:
declare module 'lodash'

What causes this error

TS2307 fires when TypeScript's module resolution algorithm can't locate the file or package referenced by an import statement. This happens when: the npm package isn't installed, the package exists but has no TypeScript type declarations (no index.d.ts and no @types package), the import path is wrong (typo, missing file extension, wrong relative path), or the tsconfig.json moduleResolution setting doesn't match the project's module system.

> advertisementAdSense placeholder

How to fix it

  1. 01

    step 1

    Check if the package is installed

    The most common cause is a missing npm install. Check node_modules for the package and your package.json for the dependency.

    // Check if installed:
    // ls node_modules/lodash
    // If missing:
    // npm install lodash
    
    // For dev-only packages:
    // npm install -D vitest
  2. 02

    step 2

    Install @types declarations for untyped packages

    Many JavaScript packages don't include TypeScript declarations. The DefinitelyTyped project provides @types/packagename packages for most popular libraries. Install them as dev dependencies.

    // Package has no built-in types — install from DefinitelyTyped
    // npm install -D @types/express
    // npm install -D @types/node
    // npm install -D @types/react
    
    // Check if @types exists:
    // npm info @types/packagename
    
    // Some packages bundle their own types (no @types needed):
    // zod, drizzle-orm, hono, effect — check for 'types' in package.json
  3. 03

    step 3

    Fix relative import paths

    For local file imports, verify the path is correct. TypeScript resolves relative imports from the importing file's location. Common mistakes: missing .js extension (required in ESM), wrong directory depth, importing a directory without an index file.

    // Wrong: file is at ./utils/helpers.ts
    import { parse } from './util/helpers'   // typo in directory name
    import { parse } from '../utils/helpers' // wrong depth
    
    // Correct
    import { parse } from './utils/helpers'
    
    // ESM with moduleResolution: 'nodenext' requires .js extension
    import { parse } from './utils/helpers.js'  // .js even for .ts files
  4. 04

    step 4

    Check tsconfig.json moduleResolution

    The moduleResolution setting controls how TypeScript looks up imports. Mismatches between your module system and resolution strategy cause TS2307. For modern projects: use 'bundler' for Vite/webpack/esbuild, 'nodenext' for Node.js ESM, or 'node' for Node.js CommonJS.

    // tsconfig.json — common configurations
    
    // For Vite, Next.js, or bundled projects:
    {
      "compilerOptions": {
        "moduleResolution": "bundler",
        "module": "esnext"
      }
    }
    
    // For Node.js ESM (package.json has "type": "module"):
    {
      "compilerOptions": {
        "moduleResolution": "nodenext",
        "module": "nodenext"
      }
    }
    
    // For Node.js CommonJS:
    {
      "compilerOptions": {
        "moduleResolution": "node",
        "module": "commonjs"
      }
    }
  5. 05

    step 5

    Declare modules for untyped packages or non-code imports

    If no @types package exists and you can't type the module fully, create a declaration file (.d.ts) with a module declaration. This is also required for non-code imports like CSS modules, images, and SVGs.

    // src/types/declarations.d.ts
    
    // Minimal declaration for an untyped package
    declare module 'some-untyped-lib' {
      export function doThing(input: string): string
      export default function main(): void
    }
    
    // CSS modules
    declare module '*.module.css' {
      const classes: Record<string, string>
      export default classes
    }
    
    // Image imports (Vite/webpack)
    declare module '*.png' {
      const src: string
      export default src
    }
    
    // SVG as React component (SVGR)
    declare module '*.svg' {
      import type { FC, SVGProps } from 'react'
      const ReactComponent: FC<SVGProps<SVGSVGElement>>
      export default ReactComponent
    }

How to verify the fix

  • Run tsc --noEmit and confirm TS2307 no longer appears
  • Verify the import resolves to the correct file (hover in VS Code to check)
  • Ensure .d.ts files are included in tsconfig.json's include or typeRoots

Why TS2307 happens at the runtime level

TS2307 is emitted by the module resolver in src/compiler/moduleNameResolver.ts when none of the resolution strategies find a matching file. TypeScript tries multiple locations in sequence: relative paths check the file system directly; bare specifiers check node_modules with various extensions (.ts, .tsx, .d.ts, .js, /index variants); and packages with 'exports' fields are resolved through the exports map. The resolution strategy is controlled by moduleResolution in tsconfig.json, and each strategy has different rules for extensions, index files, and package.json fields. If every strategy fails, TS2307 is emitted.

Common debug mistakes for TS2307

  • Forgetting to run npm install after cloning a repo or adding a new dependency to package.json.
  • Using moduleResolution 'node' with a project that uses package.json 'exports' fields — switch to 'bundler' or 'nodenext'.
  • Importing from a path alias (like @/utils) without configuring 'paths' in tsconfig.json.
  • Missing .js extension on relative imports when using moduleResolution 'nodenext' — TypeScript requires .js even for .ts source files.
  • Overriding typeRoots in tsconfig.json without including node_modules/@types, which breaks all @types resolution.

When TS2307 signals a deeper problem

Chronic TS2307 errors across a project usually indicate a mismatch between the build tool's module resolution and TypeScript's configuration. Bundlers like Vite and webpack resolve imports differently than TypeScript — they support path aliases, CSS imports, and extensionless paths that TypeScript doesn't understand by default. The fix is alignment: set moduleResolution to 'bundler' for bundled projects, configure paths in tsconfig.json to match bundler aliases, and add declaration files for non-code imports. When TypeScript and the bundler agree on how imports resolve, TS2307 stops being a constant irritant.

Editor's take

TS2307 is the most frustrating TypeScript error for beginners because it has nothing to do with your code's logic — it's a tooling configuration problem. Your code might be perfectly correct, but TypeScript can't find the file you're importing, so it refuses to compile. The fix is almost always one of four things: install the package, install its @types, fix the import path, or fix your tsconfig.json. But knowing which one requires understanding how module resolution actually works.

The moduleResolution setting is the most impactful tsconfig option for TS2307. The 'bundler' option, added in TypeScript 5.0, finally solved the chronic mismatch between how bundlers and TypeScript resolve imports. Before 'bundler', projects using Vite or webpack had to choose between 'node' (which didn't support package.json exports) and 'nodenext' (which required .js extensions on every import). Now 'bundler' gives you exports support without extension requirements — matching what bundlers actually do.

The '@types' ecosystem is TypeScript's solution for JavaScript packages that ship without type declarations. When you import lodash and get TS2307, it's not because lodash isn't installed — it's because lodash ships plain JavaScript with no .d.ts files. The @types/lodash package from DefinitelyTyped provides those declarations. This split is confusing but practical: library authors who don't use TypeScript don't need to maintain types, and the community can update them independently.

The most subtle TS2307 trigger is path aliases. Writing import { utils } from '@/lib/utils' requires both a bundler alias and a TypeScript paths mapping in tsconfig.json. Missing either one causes TS2307 in the editor but the build might still work — or vice versa. Keep them in sync, or use vite-tsconfig-paths to derive one from the other.

By Bikram Nath · Curator · Updated June 2026

Frequently asked questions

Why do I get TS2307 for .css, .svg, or .png imports?

TypeScript only understands .ts, .tsx, .js, .jsx, and .json files by default. Non-code imports (CSS, images, SVGs) are handled by your bundler (Vite, webpack, esbuild) at build time, but TypeScript doesn't know about them. You need a declaration file (.d.ts) that tells TypeScript what type these imports produce. Most frameworks provide these declarations — Next.js has next-env.d.ts, Vite has vite/client. If yours doesn't, create a declarations.d.ts in your src directory.

What's the difference between moduleResolution 'node', 'nodenext', and 'bundler'?

'node' uses Node.js CommonJS resolution: no file extensions required, checks index.js in directories, looks in node_modules. 'nodenext' uses Node.js ESM resolution: requires .js file extensions on relative imports, respects package.json 'exports' fields, and supports both ESM and CJS. 'bundler' is like 'nodenext' but doesn't require file extensions — it assumes a bundler will resolve imports. Use 'bundler' for Vite/webpack projects, 'nodenext' for Node.js libraries, and 'node' only for legacy CommonJS projects.

The package is installed but TS2307 still fires. What's wrong?

Several possibilities: the package's types are in a subpath (import from 'pkg/subpath' but types only cover 'pkg'), the package uses 'exports' in package.json and your moduleResolution doesn't support it (switch to 'bundler' or 'nodenext'), there's a monorepo workspace resolution issue (check that the workspace package is linked), or your tsconfig.json 'typeRoots' overrides the default and doesn't include node_modules/@types. Check the package's package.json for 'types' or 'exports' fields.

disclosure:Errordex runs AdSense, has zero third-party affiliate or sponsored links, and occasionally links to the editor’s own paid digital products (clearly labelled). Every fix is cross-referenced against the official sources listed in the “sources” sidebar before it ships. If a fix here didn’t work for you, please email so we can update the page.