Не удалось найти файл объявления для модуля 'module-name'. '/path/to/module-name.js' неявно имеет тип 'any'

Я читал, как работает разрешение модуля TypeScript.

У меня есть следующий репозиторий: ts-di. После компиляции структура каталогов выглядит следующим образом:

├── dist
│   ├── annotations.d.ts
│   ├── annotations.js
│   ├── index.d.ts
│   ├── index.js
│   ├── injector.d.ts
│   ├── injector.js
│   ├── profiler.d.ts
│   ├── profiler.js
│   ├── providers.d.ts
│   ├── providers.js
│   ├── util.d.ts
│   └── util.js
├── LICENSE
├── package.json
├── README.md
├── src
│   ├── annotations.ts
│   ├── index.ts
│   ├── injector.ts
│   ├── profiler.ts
│   ├── providers.ts
│   └── util.ts
└── tsconfig.json

В моем package.json я написал "main": "dist/index.js",

В Node.js все отлично работает, но TypeScript:

import {Injector} from 'ts-di';

Не удалось найти файл объявления для модуля 'ts-di'. "/path/to/node_modules/ts-di/dist/index.js" неявно имеет тип "любой".

И все же, если я импортирую следующим образом, то все работает:

import {Injector} from '/path/to/node_modules/ts-di/dist/index.js';

Что я делаю неправильно?

46 ответов

Решение

Это чувство, когда вы наблюдаете два дня и находите это так: просто удалите .js от "main": "dist/index.js" в package.json и все работает отлично!

"main": "dist/index",

UPD: этот ответ относительно, если у вас есть собственный пакет npm, если нет - см. Мой ответ ниже.

И если выше ответ не решен импортировать ваш модуль, попробуйте просто добавить typings в package.json:

"main": "dist/index",
"typings": "dist/index",

Конечно, здесь папка dist - это место, где хранятся файлы вашего модуля.

Еще два способа, когда модуль не ваш - просто попробуйте установить его из @types:

npm install -D @types/module-name

Или, если установить с ошибкой - попробуйте переписать import в require:

// import * as yourModuleName from 'module-name';
const yourModuleName = require('module-name');

Если вы импортируете сторонний модуль 'foo' который не обеспечивает никаких типов, ни в самой библиотеке, ни в @types/foo пакет (генерируется из репозитория DefintelyTyped), то вы можете устранить эту ошибку, объявив модуль в .d.ts файл:

// foo.d.ts
declare module 'foo';

Потом при импорте foo это будет просто напечатано как any,


В качестве альтернативы, если вы хотите свернуть свои собственные наборы, вы также можете сделать это:

// foo.d.ts
declare module 'foo' {
    export function getRandomNumber(): number
} 

Тогда это будет правильно скомпилировано:

import { getRandomNumber } from 'foo';
const x = getRandomNumber(); // x is inferred as number

Вам не нужно предоставлять полную типизацию для модуля, достаточно только для тех битов, которые вы на самом деле используете (и вам нужны правильные типизации), поэтому это особенно легко сделать, если вы используете довольно небольшое количество API.


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

declare module '*';

Преимущество (и недостаток) в том, что вы можете импортировать абсолютно все, и TS будет компилироваться.

Если вам нужно быстрое исправление, просто добавьте это перед импортом:

// @ts-ignore

Для всех, кто это читает, попробуйте переименовать ваш файл.js в.ts.

Изменить: вы также можете добавить "allowJs": true в ваш файл tsconfig.

TypeScript в основном реализует правила и добавляет типы в ваш код, чтобы сделать его более понятным и точным из-за отсутствия ограничений в Javascript. TypeScript требует от вас описания ваших данных, чтобы компилятор мог проверить ваш код и найти ошибки. Компилятор сообщит вам, используете ли вы несовпадающие типы, выходите ли вы из области видимости или пытаетесь ли вы вернуть другой тип. Поэтому, когда вы используете внешние библиотеки и модули с TypeScript, они должны содержать файлы, описывающие типы в этом коде. Эти файлы называются файлами объявлений типов с расширением. d.ts, Большинство типов объявлений для модулей npm уже написаны, и вы можете включить их, используя npm install @types/module_name (где имя_модуля - это имя модуля, типы которого вы хотите включить).

Тем не менее, существуют модули, которые не имеют своих определений типов, и чтобы устранить ошибку, импортируйте модуль, используя import * as module_name from 'module-name'создать папку typings в корне вашего проекта, внутри создайте новую папку с именем вашего модуля и в этой папке создайте module_name.d.ts файл и запись declare module 'module_name', После этого просто зайдите в свой tsconfig.json файл и добавить "typeRoots": [ "../../typings", "../../node_modules/@types"] в compilerOptions (с правильным относительным путем к вашим папкам), чтобы TypeScript знал, где он может найти определения типов ваших библиотек и модулей и добавить новое свойство "exclude": ["../../node_modules", "../../typings"] в файл. Вот пример того, как должен выглядеть ваш файл tsconfig.json:

{
    "compilerOptions": {
        "module": "commonjs",
        "noImplicitAny": true,
        "sourceMap": true,
        "outDir": "../dst/",
        "target": "ESNEXT",
        "typeRoots": [
            "../../typings",
            "../../node_modules/@types"
        ]
    },
    "lib": [
            "es2016"
    ],
    "exclude": [
        "../../node_modules",
        "../../typings"
    ]
}

После этого ошибка исчезнет, ​​и вы сможете придерживаться последних правил ES6 и TypeScript.

Этот способ работает для меня:

1. добавьте свою собственную декларацию в файл декларации, такой как index.d.ts(возможно, в корне проекта)
declare module Injector;
2. добавьте ваш index.d.js в tsconfig.json
  {
    "compilerOptions": {
        "strictNullChecks": true,
        "moduleResolution": "node",
        "jsx": "react",
        "noUnusedParameters": true,
        "noUnusedLocals": true,
        "allowSyntheticDefaultImports":true,
        "target": "es5",
        "module": "ES2015",
        "declaration": true,
        "outDir": "./lib",
        "noImplicitAny": true,
        "importHelpers": true
      },
      "include": [
        "src/**/*",
        "index.d.ts",   // declaration file path
      ],
      "compileOnSave": false
    }

К сожалению, это не в наших руках, возится ли автор пакета с файлом объявления. Я стараюсь иметь такой файлindex.d.ts который будет содержать все недостающие файлы объявлений из различных пакетов:

Index.ts:

declare module 'v-tooltip';
declare module 'parse5';
declare module 'emoji-mart-vue-fast';
      Just create a file named "typings.d.ts" in the root directory of your project. 
Inside this file just add "declare module "<module_name>". Here, module_name can be any module's name that you want to import. Finally, open the tsconfig.json file and include the file "typings.d.ts" inside the array named as "include array".

// typings.d.ts 
declare module 'abc-module';

// tsconfig.json 
{
  ...
"include": [
    "src", "typings.d.ts"
  ]
}

// BOOM, Problem solved!!!

This technique provides your module with a type named "any".
For more info: https://medium.com/@steveruiz/using-a-javascript-library-without-type-declarations-in-a-typescript-project-3643490015f3

Это сработало для меня.

      // modules.d.ts 
declare module 'my-module';
      // tsconfig.json 
{
  ...
  "include": [
    ...
    "src", "modules.d.ts"
  ]
}

      // Import
import * as MyModule from 'my-module'
...
const theModule = MyModule()
...

Так я и заработал.

В моем случае я использовал библиотеку, в которой не определены типы: react-mobile-datepicker

а. Создайте папку внутри /src. В моем случае я использовал этот путь: /src/typings/.

б. Создать .d.tsфайл. Для моего примера: /src/typings/react-mobile-datepicker.d.ts

c. Я использовал следующий код, чтобы расширить его свойства и сделать его безопасным по типу:

      declare module 'react-mobile-datepicker' {
  class DatePicker extends React.Component<DatePickerProps, any> {}

  interface DatePickerProps {
    isPopup?: boolean;
    theme?: string;
    dateConfig?: DatePickerConfig;
  }

  export interface DatePickerConfig {
    prop1: number;
    pro2: string;
  }
  export default DatePicker;
}

d. Импортируйте свои типы, как обычно, если вы используете стороннюю библиотеку.

      import DatePicker, { DatePickerConfig, DatePickerConfigDate } from 'react-mobile-datepicker';

е. Изменять tsconfig.json и добавьте этот фрагмент кода:

      {
  "compilerOptions": {
    //...other properties
    "typeRoots": [
      "src/typings",
      "node_modules/@types"
    ]
  }}

Ссылки на статьи, которые я использовал как источник:

https://templecoding.com/blog/2016/03/31/creating-typescript-typings-for-existing-react-components

https://www.credera.com/insights/typescript-adding-custom-type-definitions-for-existing-libraries

Решение: все, что вам нужно сделать, это отредактировать файл конфигурации TypeScript. tsconfig.json и добавьте новую пару "ключ-значение" как

      "compilerOptions": {
"noImplicitAny": false
}

У меня была та же проблема с использованием модуля узла с приложением реагирования, написанным на машинописи. Модуль был успешно установлен с помощью npm i --save my-module, Он написан на JavaScript и экспортирует Client учебный класс.

С:

import * as MyModule from 'my-module';
let client: MyModule.Client = new MyModule.Client();

Компиляция завершается с ошибкой:

Could not find a declaration file for module 'my-module'. 
'[...]/node_modules/my-module/lib/index.js' implicitly has an 'any' type.
  Try `npm install @types/my-module` if it exists or add a new declaration (.d.ts) file containing `declare module 'my-module';`

@types/my-module не существует, поэтому я добавил my-module.d.ts файл рядом с тем, где my-module импортируется с предложенной строкой. Я тогда получил ошибку:

Namespace '"my-module"' has no exported member 'Client'.

Клиент фактически экспортируется и работает нормально, если я использую его в приложении js. Также, предыдущее сообщение говорит мне, что компилятор ищет нужный файл (/node_modules/my-module/lib/index.js определяется в my-module/package.json"main" элемент).

Я решил проблему, сказав компилятору, что меня не волнует неявное anyя установил false следующая строка tsconfig.json файл:

    "noImplicitAny": false,

Проверить "tsconfig.json" файл для параметров компиляции "include" а также "exclude". Если он не существует, просто добавьте их, сообщив в корневой каталог.

// tsconfig.json
{
  "compilerOptions": {
  ...
  "include": [
    "src", 
  ],
  "exclude": [
    "node_modules", 
  ]
}

Я решил свою глупую проблему, просто удалив оператор расширения "*.spec.ts" из "exclude", потому что при включении "import" в этих файлах всегда были проблемы.

Просто исправить это:

// example.d.ts
declare module 'foo';

если вы хотите объявить интерфейс объекта (рекомендуется для большого проекта), вы можете использовать:

// example.d.ts
declare module 'foo'{
    // example
    export function getName(): string
}

Как это использовать? просто..

const x = require('foo') // or import x from 'foo'
x.getName() // intellisense can read this

В большинстве случаев вы, скорее всего, установите пакет типов для своей зависимости, в любом случае вы можете добавить allowJs -> true в свой файл tsconfig.json.

В моем случае 3 разных способа решения этой проблемы не работают. Как только вы установите «тип» как «модуль» в package.json, он будет соответствовать синтаксису модуля ES вместо CommonJS. Я смог решить эту проблему, используя синтаксис модуля ES в соответствии с моими настройками package.json.

      import ws from 'ws'

export const create = (/** @type {string} */ accessToken) => {
    const WebSocket = ws;
    return new WebSocket(endpoint, accessToken, sslOptions);
}

Таким образом, вы можете использовать класс WebSocket в модуле «ws». Это пример модуля узла, но вы можете поместить в него любой тип модуля узла и функции.

Они НЕ работают для меня ниже:

  1. npm install -D @types/module-name
  2. const foo = require('module-name');
      // index.d.ts
declare module 'foo';
  1. конфигурации из tsconfig.json
      "noImplicitAny": true,
"allowJs": true

Вам нужно отредактировать файл конфигурации TypeScript (tsconfig.json) и добавить новую пару ключ-значение как:

"noImplicitAny": false

Например: "noImplicitAny": false, "allowJs": true, "skipLibCheck": true, "esModuleInterop": true, продолжить....

Если вы установили модуль и по-прежнему получаете сообщение об ошибке, короткое и приятное решение - игнорировать сообщение об ошибке, добавив следующую строку над этой строкой

      // @ts-ignore: Unreachable code error

Ответы от @ktretyak и @Retsam верны, но я хотел бы добавить полный пример в реальном времени и то, что мне нужно было сделать:

Ошибка:

Ошибка TS7016 (TS) Не удалось найти файл декларации для модуля «response-region-select».

C:/Repo/node_modules/react-region-select/lib/RegionSelect.js неявно имеет тип any.

Попробуйте, если он существует, или добавьте новый файл объявления (.d.ts), содержащий `declare module

Бег npm i --save-dev @types/react-region-select выдает ошибку:

npm ERR! код E404

npm ERR! 404 Not Found - GET https://registry.npmjs.org/@types%2freact-region-select - Не найдено

npm ERR! 404 '@types / [email protected] ' отсутствует в реестре npm.

npm ERR! 404 Вы должны вывести автора из строя, чтобы опубликовать его (или используйте это имя самостоятельно!)

npm ERR! 404 Обратите внимание, что вы также можете установить из архива npm, папки, URL-адреса http или URL-адреса git.

Учитывая, что create-react-app создает файл с именем react-app-env.d.ts Я пытался поставить declare module 'react-region-select'; там, но я все равно получил ошибку.

Затем я создал новую папку в src называется typings и файл с именем react-region-select.d.ts. Там я объявил модуль так:

      declare module 'react-region-select';

После этого ошибка исчезла, и я мог импортировать ее, как указано в документации:

      import RegionSelect from "react-region-select"; 

https://github.com/casavi/react-region-select

Я здесь все перепробовал, но для меня это была совсем другая проблема: мне пришлось удалить из своего *.d.ts любые операторы импорта:

import { SomeModuleType } from '3rd-party-module';

После удаления ошибка ушла...

Уточнение: когда мы объявляем модуль в*.d.tsфайл, он автоматически подобрал компилятор машинописи как окружающая среду модуль (тот, который вы не должны импорт явно). Как только мы укажемimport ... from ..., файл теперь становится обычным (ES6) модулем и, следовательно, не будет получен автоматически. Поэтому, если вы все еще хотите, чтобы вести себя как окружающую среду модуль, использовать другой стиль импорта как так:

type MyType: import('3rd-party-module').SomeModuleType;

Я столкнулся с той же проблемой со многими пакетами во многих проектах. Итак, я создал Declarator, пакет npm, который автоматически генерирует объявления типов.

Это в основном работает, запустив tsc --emitDeclarationOnly на заднем фоне.

Вы можете установить его из npm:

      npm install --save-dev declarator
yarn add -D declarator

Затем создайте простой declarator.json файл:

      {
  "$schema": "https://raw.githubusercontent.com/ArthurFiorette/declarator/master/schema.json",
  "packages": ["package1","package2"]
}

И создадим скрипт для его запуска:

Использование сценария postinstall будет запускать его при каждой установке пакета, может быть полезно

      {
  "scripts": {
    "postinstall": "declarator"
  }
}

Он не будет генерировать мощные типы, и вы, вероятно, столкнетесь со многими any типы по ходу дела, но с ними намного лучше, чем без

Подробнее: https://github.com/ArthurFiorette/declarator#readme

Если вы видите эту ошибку в Webstorm и только что установили пакет, вам может потребоваться перезапустить службу машинописного текста , прежде чем она ее загрузит.

  • Откройте меню помощи
  • Найдите действие
  • Ищи Restart Typescript Service

Проблема в том, что у вас настроен машинописный текст со «старым»moduleResolution. Если вы редактируетеtsconfig.jsonиметьmoduleResolution: "nodenext", он правильно найдет типы изpackage.jsonопределения.

К сожалению, это, вероятно, вызовет много головной боли в вашем текущем репозитории.

Поэтому вы можете использовать этот обходной путь:

Добавьте файл реэкспорта для каждой записи, которая находится не в том пути, который считает TS.

Итак, в вашем случае вы бы добавили/index.tsк вашему пакету (да, с.tsрасширение, не конвертировать в.js), и он должен содержать просто

      // Stub to make TS happy. Do not add an extension to the import!
export * from "./dist"

Путь, который вы реэкспортируете, не должен иметь расширений, чтобы TS попыталась разрешить его и найтиindex.d.tsтипы файла, который к нему подключен. Если ваш файл типов не назван так, чтобы TS нашел его при импорте из JavaScript, вам придется переименовать его.

Если вы создаете пакет с экспортом , применяется то же самое. Предположим, у вас есть экспорт/viteкоторый загружается из/dist/vite.mjs, вам нужно добавить файл/vite/index.tsчто делаетexport * from "../dist/vite". Только TS будет читать этот файл.

Я тоже это получал, на какое-то время я был сбит с толку, даже с уже установленным модулем и типами и перезагружал мою IDE несколько раз.

Что исправило в моем случае, так это завершение терминальных процессов, удаление node_modules, очистив кеш менеджера пакетов узла и сделав свежий install затем перезагрузите редактор.

Основываясь на ответе Ретсама , вы также можете использовать подстановочные знаки () в yourDeclarations.d.tsфайл. Например, если вы пытаетесь импортировать файл, такой как .cssили файл, вы можете разместить *в начале объявления типа файла. Это будет выглядеть примерно так ⤵︎

      declare module '*.webp';

Теперь вы можете импортировать все .webpфайлы, которые вы хотите, без каких-либо ошибок линтинга.

может вам понадобится создать файл с .d.ts расширение.

вставьте это имя файла в include ключ от tsconfig.json файл:

        "include": [
    "src",
    "index.d.ts"
  ]

это должно быть работа

В моем случае добавление псевдонима путей сработало, и машинописный текст нашел файл объявления:

      // tsconfig.json
{
    "compilerOptions": {
        ...
        paths: {
            "*": ["@types/*"]
        }
    }
}

А затем добавьте необходимые файлы объявлений в папку @types/ :

      declare module 'not-found-module' {
    // your declations
}

Для меня работает то, что зависимости устанавливаются как зависимости dev. Вышеупомянутое решение по отключению неявной проверки типов работает, но это удерживает меня от использования строго типизированного кода. Итак, что вам нужно сделать, это просто добавить все установки модуля @types с флагом --save-dev. Надеюсь, это сработает и для вас

Если импорт у вас не работает

      import * as html2pdf from 'html2pdf.js';

Прокомментируйте код, сохраните указанный ниже файл сценария в index.html, как указано в официальных документах.

      <script src="https://rawgit.com/eKoopmans/html2pdf/master/dist/html2pdf.bundle.min.js"></script>

И объявите переменную html2pdf в используемом вами компоненте.

      declare var html2pdf: any;

Вот и все. Я застрял в этой проблеме в течение 2 дней, но, наконец, решил, что она решена.

Другие вопросы по тегам