TypeScript "Cannot find module 'X' or its corresponding type declarations" in CI
tsc could not locate either the module or a type declaration for an import. In CI this usually means the package (or its @types/* companion) is not installed, or it lives in devDependencies that were pruned.
What this error means
A build that compiles locally fails in CI with TS2307 on an import. The path is correct, but tsc reports it cannot find the module or its .d.ts. Often only a subset of imports fail.
src/api/client.ts:3:24 - error TS2307: Cannot find module 'lodash'
or its corresponding type declarations.
3 import groupBy from 'lodash';
~~~~~~~~Common causes
The package or its @types is not installed
A runtime dependency was added but never saved to package.json, or its types live in a separate @types/x package that was not installed. CI installs only what the lockfile lists.
The dependency is a devDependency pruned in CI
Type packages belong in devDependencies. If CI runs npm ci --omit=dev, those @types/* packages are absent at compile time.
A custom path or types resolution mismatch
A paths alias or a typeRoots setting that works locally points somewhere that does not exist in the CI checkout, so tsc resolves nothing.
How to fix it
Install the package and its types
Add both the runtime package and its @types/* companion to package.json so they are in the lockfile.
- Install the runtime dep: npm install lodash.
- Install its types as a devDependency: npm install -D @types/lodash.
- Commit the updated package.json and lockfile.
npm install lodash
npm install -D @types/lodashDo not prune dev types in a build job
A job that compiles TypeScript needs devDependencies. Use a full install for build jobs and reserve --omit=dev for runtime-only deploy artifacts.
# build job
npm ci # installs devDependencies too
npm run buildHow to prevent it
- Keep
@types/*packages in devDependencies and never prune them in build jobs. - Run
npm run build(ortsc --noEmit) in CI on a clean checkout to catch missing deps. - Add a
declare moduleshim only as a last resort for packages that genuinely ship no types.