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

303

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

У меня есть следующий репозиторий: @ ts-stack / 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-stack/di';

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

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

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

Что я делаю не так?

ktretyak
источник

Ответы:

295

Вот два других решения

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

npm install -D @types/module-name

Если вышеприведенные ошибки установки - попробуйте изменить importоператоры на require:

// import * as yourModuleName from 'module-name';
const yourModuleName = require('module-name');
ktretyak
источник
13
Если вы не можете найти имя, запустите это для TypeScript 2.0:npm install @types/node --save-dev
Ogglas
120
Что если модуль не имеет пакета @types?
Даниэль Кмак
37
Я думаю, что использование requireвместо import- это немного против паттерна: лучше объявить модуль в .d.tsфайле; см. мой ответ ниже.
Рецам
2
Пример использования: const mdbreact = require('mdbreact'); const { Button, Card, CardBody, CardText, CardTitle, CardImage } = mdbreact;
Sgedda
1
Это плохой совет. Это полностью сводит на нет смысл TypeScript и общую позицию FOSS о том, что «что-то достаточно простое стоит внести свой вклад». Если при наборе текста отсутствует, кто-то выполнил поиск, а кто-то не опубликовал, или отправил PR с вашими наборами, или не используйте систему набора, если вы просто хотите обойти это.
Дэйв Макинтош
266

Если вы импортируете сторонний модуль 'foo', который не предоставляет никаких типизаций, ни в самой библиотеке, ни в @types/fooпакете (сгенерированном из репозитория DefiniteTyped ), то вы можете устранить эту ошибку, объявив модуль в файл с .d.tsрасширением. TypeScript ищет .d.tsфайлы в тех же местах, что и обычные .tsфайлы: как указано в «files», «include» и «exclude» в tsconfig.json.

// 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 будет компилироваться.

Retsam
источник
27
где компилятор ищет d.tsфайлы? Вы должны предоставить какие-либо настройки, такие как typeRoots?
Том
17
@Tom Он ищет .d.tsфайлы в тех же местах, что и обычные .tsфайлы: как указано «files», «include» и «exclude» в tsconfig.json. Я не рекомендовал бы использовать typeRootsдля этой цели: это предназначено для расположения модулей внешнего типа (то есть node_modules/@types), а не отдельных .d.tsфайлов.
Рецам
3
Я получаю "файл foo.d.ts не является модулем"
Натан Х
2
Похоже, этот подстановочный файл нужно называть «typings.d.ts»
jacob
4
Где я должен положить этот .d.tsфайл?
tonix
127

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

// @ts-ignore
Лиран Х
источник
7
Спасибо, самый полезный ответ для моего случая.
Дэвид
Это вызывает ошибку в более поздних версиях eslint:error Do not use "// @ts-ignore" comments because they suppress compilation errors @typescript-eslint/ban-ts-ignore
Hykilpikonna
91

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

"main": "dist/index",

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

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

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

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

ktretyak
источник
Я приходил к вашему вопросу и вашему ответу много раз в последние дни, и я хотел бы добавить, что мне не хватало, чтобы объявить эти типы в файле .d.ts, поэтому в моем случае были установлены модули узлов, которые поставлялись без типы (и я не смог установить explicity их типы) начали работать, объявив их в этом файле, написав "объявлять модуль 'MYDesiredModule'
Juan
Спасибо. Добавление «typings»: «dist / index» в мой package.json помогло мне. Странно, что VS Code выдает ошибку машинописного
текста,
Спасибо за ваше понимание! Не могли бы вы сказать мне, почему определения VS Code не работают для моего собственного пакета npm, если я пытаюсь перейти к определениям? Я создал здесь вопрос, и мне пока не повезло ... stackoverflow.com/questions/59128917/…
tonix
вам нужно добавить файл «index.d.ts» в папку dist и положить declare module "moduleName" в это время
Sunny Sun
43

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(с соответствующим относительным путем к папкам) , чтобы машинопись знать , где он может найти типы определения библиотек и модулей и добавить новое свойство "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.

Марко Рочевский
источник
Это сработало только для меня, если бы я назвал файл наборов index.d.ts. Кроме этого, это было единственное решение, которое помогло мне.
Крис Хейнс
21

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

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

Мартин Локетт
источник
да, та же проблема была с «реакцией-слиянием», и это решение работало как шарм.
зевая
16

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

1. добавьте свою собственную декларацию в файл декларации, такой как index.d.ts (возможно, в корне проекта)
declare module 'Injector';
2. добавьте ваш index.d.ts в 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
    }

- изменить: необходимые кавычки вокруг имени модуля

Lumaskcete
источник
4

У меня была та же проблема с использованием модуля узла с приложением реагирования, написанным на машинописи. Модуль был успешно установлен с помощью 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,
Kanthavel
источник
14
Я имею в виду, это работает, но вы теряете возможность строго набирать остальную часть вашего кода. Это не отличный обходной путь.
Phillyslick
3

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

// 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
Абдул Азиз Аль Басыр
источник
2

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

В моем случае это исправляло завершение процессов терминала, удаление node_modules, очистку кэша диспетчера пакетов узла и installповторную загрузку редактора.

Лео
источник
2

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

Index.ts:

declare module 'v-tooltip';
declare module 'parse5';
declare module 'emoji-mart-vue-fast';
Люк Гарриган
источник
0

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

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

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

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

type MyType: import('3rd-party-module').SomeModuleType;
Ильяс Ассаинов
источник
-1

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

npm install --save readline

honkskillet
источник
-4

Просто вы можете импортировать его, используя require как следующий код:

var _ = require('your_module_name');
Эр-Рияд Халифе
источник