НейроАгент

Как настроить импорт модулей в TypeScript 5.x

Решаем проблему 'Cannot find module' в TypeScript 5.x. Настройка moduleResolution, CommonJS/ES модулей и ts-node-dev. Полное руководство для разработчиков.

Как решить проблему с импортом модулей при сборке TypeScript проекта?

Проект перестал запускаться с ошибкой: “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”. Редактор кода находит файл и предлагает автодополнение, но терминал не может разрешить путь к модулю.

Что удалось выяснить:

  • Обновился TypeScript, который теперь ругается на параметр Node в ModuleResolution как устаревший
  • При смене на Bandler возникает несовместимость с системой модулей CommonJS
  • Требуется менять разные параметры для запуска бэкенда и проверки типов

Текущая конфигурация:

  • TypeScript: 5.7.3
  • ts-node-dev: 2.0.0
  • Команда запуска: npm run devts-node-dev --watch ./.env --rs --exit-child ./src/index.ts

Ошибка при запуске:

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

Как настроить согласованную конфигурацию для работы и проверки типов?

НейроАгент

TypeScript не может найти модуль из-за устаревших настроек разрешения модулей и несогласованности между CommonJS и ES модулями. Для решения проблемы необходимо обновить конфигурацию TypeScript, настроить правильные параметры разрешения модулей и обеспечить совместимость между инструментами разработки и выполнения.

Содержание

Основные причины ошибки разрешения модулей

Ошибка “Cannot find module” возникает из-за нескольких распространенных причин:

  1. Устаревшие параметры ModuleResolution - TypeScript 5.x помечает параметр “node” как устаревший, что вызывает конфликты
  2. Несогласованность между системами модулей - проект использует CommonJS, но инструменты пытаются работать с ES модулями
  3. Неправильные пути к файлам - относительные или абсолютные пути не соответствуют ожиданиям компилятора
  4. Отсутствие файлов деклараций - для некоторых модулей отсутствуют типы (.d.ts файлы)

Важно: Ваш редактор кода находит файлы, потому что использует собственный механизм разрешения путей, который отличается от того, что использует TypeScript при компиляции.

Настройка ModuleResolution в TypeScript 5.x

В TypeScript 5.x произошли изменения в системе разрешения модулей. Параметр moduleResolution: "node" теперь считается устаревшим и заменяется на moduleResolution: "bundler" для современных проектов.

Конфигурация tsconfig.json

json
{
  "compilerOptions": {
    "module": "CommonJS",
    "moduleResolution": "NodeNext", // или "Node16"
    "target": "ES2020",
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "resolveJsonModule": true,
    "declaration": true,
    "outDir": "./dist",
    "rootDir": "./src"
  }
}

Варианты для moduleResolution:

  • NodeNext - для смешанных CommonJS/ES проектов
  • Node16 - для проектов, соответствующих Node.js 16+ module resolution
  • Bundler - для современных сборщиков (Vite, esbuild, webpack)

Конфигурация для CommonJS и ES модулей

Проблема совместимости

Ваша ситуация типична для проектов, которые мигрируют между CommonJS и ES модулями. Вот что нужно учитывать:

  1. Если проект использует CommonJS:

    • Установите module: "CommonJS"
    • Используйте moduleResolution: "NodeNext"
    • Добавьте esModuleInterop: true
  2. Если проект использует ES модули:

    • Установите module: "ES2022" или выше
    • Используйте moduleResolution: "Bundler"
    • Добавьте allowImportingTsExtensions: true

Пример для вашего проекта

json
{
  "compilerOptions": {
    "module": "CommonJS",
    "moduleResolution": "NodeNext",
    "target": "ES2020",
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "baseUrl": "./src",
    "paths": {
      "@lib/*": ["lib/*"],
      "@/*": ["./*"]
    }
  }
}

Настройка ts-node-dev для корректной работы

Проблема с ts-node-dev часто возникает из-за несогласованности между настройками TypeScript и параметрами запуска.

Обновление команды запуска

Вместо текущей команды:

bash
ts-node-dev --watch ./.env --rs --exit-child ./src/index.ts

Используйте:

bash
ts-node-dev --watch ./.env --rs --exit-child --respawn --transpile-only ./src/index.ts

Альтернативные варианты запуска

  1. Использование tsx (современная альтернатива):
bash
npm install -D tsx
json
{
  "scripts": {
    "dev": "tsx --watch --env-file ./.env ./src/index.ts"
  }
}
  1. Использование ts-node с правильными флагами:
bash
ts-node --esm --transpile-only ./src/index.ts

Конфигурация ts-node

Создайте файл ts-node.config.js:

javascript
module.exports = {
  compilerOptions: {
    module: "CommonJS",
    moduleResolution: "NodeNext",
    target: "ES2020",
    esModuleInterop: true,
    allowSyntheticDefaultImports: true,
    baseUrl: "./src",
    paths: {
      "@lib/*": ["lib/*"],
      "@/*": ["./*"]
    }
  }
};

Практическое решение для вашего проекта

Для решения вашей конкретной проблемы с импортом /home/andrew/CODE/JS/React/IdeaNick/backend/src/lib/ctx выполните следующие шаги:

1. Обновите tsconfig.json

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. Обновите package.json scripts

json
{
  "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. Проверьте импорты

Убедитесь, что ваши импорты соответствуют структуре проекта:

typescript
// Правильные варианты импорта
import { someFunction } from './lib/ctx';
import { someFunction } from '@/lib/ctx';
import { someFunction } from '@lib/ctx';

// Избегайте абсолютных путей вне конфигурации
// import { someFunction } from '/home/andrew/CODE/JS/React/IdeaNick/backend/src/lib/ctx';

4. Создайте файлы деклараций (если нужно)

Если у вас есть модули без типов, создайте src/lib/ctx.d.ts:

typescript
declare module 'ctx' {
  export function someFunction(): void;
  export const someValue: string;
}

Проверка и тестирование конфигурации

После внесения изменений выполните следующие проверки:

1. Проверка типов

bash
npm run type-check

2. Проверка сборки

bash
npm run build

3. Проверка запуска

bash
npm run dev

4. Проверка импортов в редакторе

Если редактор по-прежнему не видит модули, попробуйте:

  1. Перезапустите VS Code
  2. Установите расширение TypeScript и ESLint
  3. Проверьте, что рабочая область использует правильную версию TypeScript

5. Отладка сложных случаев

Если проблема остается, добавьте в tsconfig.json:

json
{
  "compilerOptions": {
    "traceResolution": true,
    "listEmittedFiles": true
  }
}

Это поможет увидеть, какие файлы TypeScript пытается найти и почему.

Источники

  1. Официальная документация TypeScript - Module Resolution
  2. GitHub TypeScript - ModuleResolution changes
  3. ts-node documentation
  4. TypeScript 5.x Migration Guide
  5. CommonJS vs ES Modules

Заключение

Для решения проблемы с импортом модулей в TypeScript проекте необходимо:

  1. Обновить конфигурацию TypeScript - использовать moduleResolution: "NodeNext" вместо устаревшего “node”
  2. Настроить согласованность между CommonJS и ES модулями - выбрать одну систему и придерживаться её
  3. Правильно сконфигурировать ts-node-dev - добавить флаг --transpile-only для ускорения разработки
  4. Использовать псевдонимы путей - настроить baseUrl и paths для удобства импортов
  5. Проверить пути к файлам - убедиться, что все относительные пути корректны

Основная проблема в вашем случае заключается в несогласованности между старыми настройками TypeScript и новой версией компилятора. После применения предложенных конфигураций ваш проект должен корректно запускаться без ошибок разрешения модулей.