Не вдалося знайти файл декларації для модуля 'ім'я модуля'. '/path/to/module-name.js' неявно має тип 'будь-який'


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

У своєму пакеті.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' неявно має тип "будь-який".

І все ж, якщо я імпортую так, то все працює:

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

Що я роблю неправильно?

Відповіді:


295

Ось два інші рішення

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

npm install -D @types/module-name

Якщо вище встановлені помилки, спробуйте змінити importоператори на require:

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

13
Якщо ви не можете знайти ім'я, запускайте це для TypeScript 2.0:npm install @types/node --save-dev
Огглас

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 з вашими типізаціями або не використовуйте систему набору тексту, якщо ви просто хочете її обійти.
Дейв Макінтош

265

Якщо ви імпортуєте сторонній модуль 'foo', який не забезпечує жодних типізацій, ні в самій бібліотеці, ні в @types/fooпакеті (згенерований з сховища DefinitelyTyped ), ви можете усунути цю помилку, оголосивши модуль у файл із .d.tsрозширенням. TypeScript шукає .d.tsфайли там, де вони шукатимуть звичайні .tsфайли: як зазначено у розділі "файли", "включити" та "виключити" в 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 буде компілювати.


27
де компілятор шукає d.tsфайли? ви повинні надати будь-яку конфігурацію , такі як typeRoots?
Том

17
@Tom Шукає .d.tsфайли там, де вони шукатимуть звичайні .tsфайли: як зазначено "файли", "включити" та "виключити" у tsconfig.json. Я б не рекомендував використовувати typeRootsдля цієї мети: це призначено для розташування модулів зовнішнього типу (тобто node_modules/@types), а не окремих .d.tsфайлів.
Ретсам

3
Я отримую "файл foo.d.ts - це не модуль"
Nathan H

2
Схоже, цей файл підстановки має бути названий "typing.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- це місце, де зберігаються файли вашого модуля.


Я останніх днів неодноразово приходив до вашого запитання та вашої відповіді, і я хотів би додати, що мені не вистачало заявити про ці типи у файлі .d.ts, тож у моєму випадку встановлені модулі вузлів, які не ввійшли типи (а мені не вдалося встановити explicity їхні типи) почали працювати, оголосивши їх у цьому файлі, написавши "оголосити модуль" MYDesiredModule "
Хуан

Дякую. Додавання "typeings": "dist / index" до мого пакету.json було те, що працювало для мене. Дивно, що код VS
видає

Дякую за ваше розуміння! Скажіть, будь ласка, чому визначення коду VS не працює для мого власного пакету npm, якщо я спробую перейти до визначень? Я створив питання тут і не щастило до сих пір ... stackoverflow.com/questions/59128917 / ...
Tonix

вам потрібно додати файл "index.d.ts" у папку dist і declare module "moduleName" тим часом поставити
Сонячне Нд

42

В основному TypeScript реалізує правила та додає типи до свого коду, щоб зробити його більш чітким та точним через відсутність обмежень у JavaScript. TypeScript вимагає описати ваші дані, щоб компілятор міг перевірити ваш код та виявити помилки. Компілятор повідомить вам про те, що ви використовуєте невідповідні типи, якщо ви не входять у сферу своєї дії або намагаєтесь повернути інший тип. Отже, коли ви використовуєте зовнішні бібліотеки та модулі з TypeScript, вони повинні містити файли, що описують типи в цьому коді. Ці файли називаються файлами декларації типу з розширенням d.ts. Більшість типів декларацій для npm-модулів вже написані, і ви можете включити їх, використовуючи npm install @types/module_name(де 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.


Це працювало для мене лише в тому випадку, якщо я назвав файл типізації 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
    }

- редагувати: потрібні лапки навколо назви модуля


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,

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;

-4

Просто ви можете імпортувати його, використовуючи вимагаючи наступний код:

var _ = require('your_module_name');
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.