How to resolve module import issues when building a TypeScript project?
The project stopped running with the error: “Cannot find module ‘/home/andrew/CODE/JS/React/IdeaNick/backend/src/lib/ctx’ imported from /home/andrew/CODE/JS/React/IdeaNick/backend/src/index.ts”. The code editor finds the file and offers autocomplete, but the terminal cannot resolve the module path.
What I’ve discovered:
- TypeScript was updated, which now complains about the Node parameter in ModuleResolution as deprecated
- When switching to Bandler, there’s an incompatibility with the CommonJS module system
- Different parameters are needed to run the backend and for type checking
Current configuration:
- TypeScript: 5.7.3
- ts-node-dev: 2.0.0
- Run command:
npm run dev→ts-node-dev --watch ./.env --rs --exit-child ./src/index.ts
Error on startup:
Error: Cannot find module '/home/andrew/CODE/JS/React/IdeaNick/backend/src/lib/ctx' imported from /home/andrew/CODE/JS/React/IdeaNick/backend/src/index.ts'
How can I configure a consistent setup for both runtime and type checking?
TypeScript Cannot Find Module Due to Outdated Module Resolution Settings and Inconsistency Between CommonJS and ES Modules
To resolve this issue, you need to update your TypeScript configuration, set up the correct module resolution parameters, and ensure compatibility between development and execution tools.
Contents
- Basic Reasons for Module Resolution Errors
- Setting Up ModuleResolution in TypeScript 5.x
- Configuration for CommonJS and ES Modules
- Setting Up ts-node-dev for Proper Operation
- Practical Solution for Your Project
- Checking and Testing Configuration
Basic Reasons for Module Resolution Errors
The “Cannot find module” error occurs due to several common reasons:
- Outdated ModuleResolution parameters - TypeScript 5.x marks the “node” parameter as deprecated, causing conflicts
- Inconsistency between module systems - the project uses CommonJS, but tools try to work with ES modules
- Incorrect file paths - relative or absolute paths don’t match the compiler’s expectations
- Missing declaration files - some modules lack types (.d.ts files)
Important: Your code editor finds files because it uses its own path resolution mechanism, which differs from what TypeScript uses during compilation.
Setting Up ModuleResolution in TypeScript 5.x
In TypeScript 5.x, there have been changes to the module resolution system. The moduleResolution: "node" parameter is now considered deprecated and is replaced with moduleResolution: "bundler" for modern projects.
tsconfig.json Configuration
{
"compilerOptions": {
"module": "CommonJS",
"moduleResolution": "NodeNext", // or "Node16"
"target": "ES2020",
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"declaration": true,
"outDir": "./dist",
"rootDir": "./src"
}
}
Options for moduleResolution:
NodeNext- for mixed CommonJS/ES projectsNode16- for projects that follow Node.js 16+ module resolutionBundler- for modern bundlers (Vite, esbuild, webpack)
Configuration for CommonJS and ES Modules
Compatibility Issue
Your situation is typical for projects that are migrating between CommonJS and ES modules. Here’s what you need to consider:
-
If the project uses CommonJS:
- Set
module: "CommonJS" - Use
moduleResolution: "NodeNext" - Add
esModuleInterop: true
- Set
-
If the project uses ES modules:
- Set
module: "ES2022"or higher - Use
moduleResolution: "Bundler" - Add
allowImportingTsExtensions: true
- Set
Example for Your Project
{
"compilerOptions": {
"module": "CommonJS",
"moduleResolution": "NodeNext",
"target": "ES2020",
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"baseUrl": "./src",
"paths": {
"@lib/*": ["lib/*"],
"@/*": ["./*"]
}
}
}
Setting Up ts-node-dev for Proper Operation
Problems with ts-node-dev often arise from inconsistency between TypeScript settings and startup parameters.
Updated Startup Command
Instead of the current command:
ts-node-dev --watch ./.env --rs --exit-child ./src/index.ts
Use:
ts-node-dev --watch ./.env --rs --exit-child --respawn --transpile-only ./src/index.ts
Alternative Startup Options
- Using tsx (modern alternative):
npm install -D tsx
{
"scripts": {
"dev": "tsx --watch --env-file ./.env ./src/index.ts"
}
}
- Using ts-node with correct flags:
ts-node --esm --transpile-only ./src/index.ts
ts-node Configuration
Create a ts-node.config.js file:
module.exports = {
compilerOptions: {
module: "CommonJS",
moduleResolution: "NodeNext",
target: "ES2020",
esModuleInterop: true,
allowSyntheticDefaultImports: true,
baseUrl: "./src",
paths: {
"@lib/*": ["lib/*"],
"@/*": ["./*"]
}
}
};
Practical Solution for Your Project
To solve your specific problem with importing /home/andrew/CODE/JS/React/IdeaNick/backend/src/lib/ctx, follow these steps:
1. Update tsconfig.json
{
"compilerOptions": {
"module": "CommonJS",
"moduleResolution": "NodeNext",
"target": "ES2020",
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"declaration": true,
"outDir": "./dist",
"rootDir": "./src",
"baseUrl": "./src",
"paths": {
"@lib/*": ["lib/*"],
"@/*": ["./*"]
}
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}
2. Update package.json Scripts
{
"scripts": {
"dev": "ts-node-dev --watch ./.env --rs --exit-child --transpile-only ./src/index.ts",
"build": "tsc",
"start": "node dist/index.js",
"type-check": "tsc --noEmit"
}
}
3. Check Imports
Make sure your imports match the project structure:
// Correct import options
import { someFunction } from './lib/ctx';
import { someFunction } from '@/lib/ctx';
import { someFunction } from '@lib/ctx';
// Avoid absolute paths outside configuration
// import { someFunction } from '/home/andrew/CODE/JS/React/IdeaNick/backend/src/lib/ctx';
4. Create Declaration Files (if needed)
If you have modules without types, create src/lib/ctx.d.ts:
declare module 'ctx' {
export function someFunction(): void;
export const someValue: string;
}
Checking and Testing Configuration
After making changes, perform the following checks:
1. Type Checking
npm run type-check
2. Build Check
npm run build
3. Startup Check
npm run dev
4. Import Check in Editor
If the editor still can’t see modules, try:
- Restart VS Code
- Install TypeScript and ESLint extensions
- Check that the workspace uses the correct TypeScript version
5. Debugging Complex Cases
If the problem persists, add to tsconfig.json:
{
"compilerOptions": {
"traceResolution": true,
"listEmittedFiles": true
}
}
This will help you see which files TypeScript is trying to find and why.
Sources
- Official TypeScript Documentation - Module Resolution
- GitHub TypeScript - ModuleResolution changes
- ts-node documentation
- TypeScript 5.x Migration Guide
- CommonJS vs ES Modules
Conclusion
To solve the module import problem in your TypeScript project, you need to:
- Update TypeScript configuration - use
moduleResolution: "NodeNext"instead of the deprecated “node” - Configure consistency between CommonJS and ES modules - choose one system and stick to it
- Properly configure ts-node-dev - add the
--transpile-onlyflag for faster development - Use path aliases - configure
baseUrlandpathsfor convenient imports - Check file paths - ensure all relative paths are correct
The main problem in your case is the inconsistency between old TypeScript settings and the new compiler version. After applying the suggested configurations, your project should start correctly without module resolution errors.