Avatar ·

Ошибка "Could not find a declaration file for module" в TypeScript — как исправить?

Приветствую! Я начинающий TypeScript-разработчик и столкнулся с проблемой при импорте стороннего модуля. У меня есть простой проект на Express.js, написанный на TypeScript. Я установил пакет `lodash` через npm, но когда пытаюсь импортировать его в своём файле `index.ts`, компилятор выдаёт ошибку. Вот мой код: ```typescript import _ from 'lodash'; const arr = [1, 2, 3, 4, 5]; const shuffled = _.shuffle(arr); console.log(shuffled); ``` При запуске `tsc` я получаю: ``` Could not find a declaration file for module 'lodash'. '/path/to/node_modules/lodash/lodash.js' implicitly has an 'any' type. Try `npm i --save-dev @types/lodash` if it exists or add a new declaration (.d.ts) file containing `declare module 'lodash';` ``` Я понимаю, что TypeScript требует файлы деклараций (`.d.ts`) для сторонних модулей, но не совсем понимаю, как это работает. Почему одни модули работают без дополнительных действий, а другие — нет? И что означает "implicitly has an 'any' type"? Я пробовал добавить `"noImplicitAny": false` в `tsconfig.json`, но это кажется костылём. Подскажите, как правильно решить эту проблему для разных модулей — с типами и без? <<>>

Причина ошибки

TypeScript — это строго типизированный язык. Когда вы импортируете модуль, компилятор ищет файл декларации типов (с расширением .d.ts), который описывает все функции, классы и типы модуля. Если такой файл отсутствует, TypeScript присваивает модулю тип any (что нарушает настройку noImplicitAny, включённую по умолчанию), и вы видите эту ошибку.

Решение: три способа

1. Установка @types/пакета (рекомендуется)

Многие популярные библиотеки имеют отдельные пакеты с декларациями в DefinitelyTyped. Для lodash это работает так:

npm install --save-dev @types/lodash

После установки TypeScript автоматически найдёт файлы деклараций в node_modules/@types/lodash, и ошибка исчезнет. Для проверки наличия типов для вашего модуля используйте поиск: npm info @types/ваш-модуль или посетите TypeScript Search.

2. Создание собственного файла декларации

Если типов нет в DefinitelyTyped или вы используете внутренний модуль, создайте файл declarations.d.ts (имя может быть любым) в корне проекта:

// declarations.d.ts
declare module 'lodash' {
  export function shuffle<T>(array: T[]): T[];
  // можно описать полный интерфейс или оставить any:
  // export function shuffle(array: any[]): any[];
}

Важно: чтобы TypeScript подхватил этот файл, он должен быть включён в include или files вашего tsconfig.json. Обычно достаточно:

{
  "compilerOptions": {
    "typeRoots": ["./node_modules/@types", "./types"]
  },
  "include": ["src/**/*", "declarations.d.ts"]
}

3. Отключение noImplicitAny (не рекомендуется)

Это временное решение, которое отключает строгую типизацию:

// tsconfig.json
{
  "compilerOptions": {
    "noImplicitAny": false
  }
}

Но это снижает безопасность кода: вы не получите подсказки IDE и можете допустить ошибки во время выполнения.

Почему одни модули работают без @types?

Некоторые библиотеки (например, express) содержат встроенные файлы деклараций — в их package.json есть поле "types", указывающее на .d.ts файл. У lodash такого поля нет, поэтому нужны внешние типы.

Дополнительные советы

  • Проверьте tsconfig.json: убедитесь, что moduleResolution установлен в "node" (по умолчанию).
  • Используйте skipLibCheck: true в опциях компилятора — это ускорит сборку, но не решит проблему с отсутствием типов.
  • Для глобальных модулей (без импорта) создайте файл globals.d.ts и объявите модуль с declare module 'lodash'.
<<>>

Альтернативный подход: использование "allowUmdGlobalAccess" и "module"

Если вы используете модуль, который распространяется как UMD (например, некоторые старые библиотеки), можно включить опцию allowUmdGlobalAccess в tsconfig.json:

{
  "compilerOptions": {
    "allowUmdGlobalAccess": true,
    "module": "commonjs" // или "esnext"
  }
}

Это позволит импортировать UMD-модули без явных деклараций, но только если они корректно объявлены. Однако это не решит проблему для чистых CommonJS-модулей без типов.

Быстрый фикс для разработки

Если вам нужно срочно продолжить работу, а типы не критичны, можно создать минимальный файл декларации с одной строкой:

// any-declarations.d.ts
declare module 'lodash' {
  const _: any;
  export default _;
}

Это даст тип any для всего модуля, но позволит избежать ошибки компиляции. Используйте только для прототипирования — на продакшене лучше установить корректные @types.

Проверка наличия встроенных типов

Некоторые модули поставляются с типами, но они могут быть скрыты. Проверьте package.json модуля:

// в node_modules/lodash/package.json
{
  "types": "index.d.ts" // если есть — типы уже установлены
}

Если поле "types" отсутствует, но вы нашли .d.ts файлы в папке модуля — просто добавьте путь к ним в typeRoots в tsconfig.json.