Không thể tìm thấy tệp khai báo cho mô-đun 'tên mô-đun'. '/path/to/module-name.js' hoàn toàn có loại 'bất kỳ'


303

Tôi đọc cách hoạt động của độ phân giải mô-đun TypeScript .

Tôi có kho lưu trữ sau: @ ts-stack / di . Sau khi biên dịch cấu trúc thư mục như sau:

├── 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

Trong gói.json của tôi, tôi đã viết "main": "dist/index.js".

Trong Node.js mọi thứ đều hoạt động tốt, nhưng TypeScript:

import {Injector} from '@ts-stack/di';

Không thể tìm thấy tệp khai báo cho mô-đun '@ ts-stack / di'. '/path/to/node_modules/@ts-stack/di/dist/index.js' mặc nhiên có loại 'bất kỳ'.

Tuy nhiên, nếu tôi nhập như sau, thì mọi thứ sẽ hoạt động:

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

Tôi đang làm gì sai?

Câu trả lời:


295

Đây là hai giải pháp khác

Khi một mô-đun không phải là của bạn - hãy thử cài đặt các loại từ @types:

npm install -D @types/module-name

Nếu lỗi cài đặt ở trên - hãy thử thay đổi importcâu lệnh thành require:

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

13
Nếu bạn không thể tìm thấy tên, hãy chạy cái này cho TypeScript 2.0:npm install @types/node --save-dev
Ogglas

120
Nếu mô-đun không có gói @types thì sao?
Daniel Kmak

37
Tôi nghĩ rằng việc sử dụng requirethay vì importlà một chút chống mẫu: tốt hơn là khai báo mô-đun trong một .d.tstệp; xem câu trả lời của tôi dưới đây
Retsam

2
Ví dụ sử dụng: const mdbreact = require('mdbreact'); const { Button, Card, CardBody, CardText, CardTitle, CardImage } = mdbreact;
Sgedda

1
Đây là lời khuyên kém. Điều này hoàn toàn phủ nhận quan điểm của TypeScript và thái độ FOSS chung của "một cái gì đó đủ dễ là đáng để đóng góp". Nếu thiếu gõ một, tìm kiếm của ai đó đã thực hiện và không được xuất bản hoặc gửi PR với các kiểu chữ của bạn hoặc không sử dụng hệ thống gõ nếu bạn chỉ muốn phá vỡ nó.
Dave Mackffy

265

Nếu bạn đang nhập mô-đun của bên thứ ba 'foo'không cung cấp bất kỳ kiểu chữ nào, trong chính thư viện hoặc trong @types/foogói (được tạo từ kho lưu trữ DefiniteTyped ), thì bạn có thể khắc phục lỗi này bằng cách khai báo mô-đun trong một tập tin với một .d.tsphần mở rộng. TypeScript tìm kiếm .d.tscác tệp ở cùng một nơi mà nó sẽ tìm .tscác tệp bình thường : như được chỉ định trong "tệp", "bao gồm" và "loại trừ" trong tsconfig.json.

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

Sau đó, khi bạn nhập, foonó sẽ được gõ là any.


Ngoài ra, nếu bạn muốn cuộn các kiểu chữ của riêng mình, bạn cũng có thể làm điều đó:

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

Sau đó, điều này sẽ biên dịch chính xác:

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

Bạn không phải cung cấp các kiểu chữ đầy đủ cho mô-đun, chỉ đủ cho các bit mà bạn thực sự đang sử dụng (và muốn đánh máy đúng cách), do đó, rất dễ thực hiện nếu bạn đang sử dụng một lượng API khá nhỏ.


Mặt khác, nếu bạn không quan tâm đến các kiểu chữ của các thư viện bên ngoài và muốn tất cả các thư viện không có kiểu chữ được nhập vào any, bạn có thể thêm phần này vào một tệp có .d.tsphần mở rộng:

declare module '*';

Lợi ích (và nhược điểm) của việc này là bạn có thể nhập hoàn toàn mọi thứ và TS sẽ biên dịch.


27
trình biên dịch tìm d.tstập tin ở đâu? Bạn nên cung cấp bất kỳ cấu hình như typeRoots?
Tom

17
@Tom Nó tìm kiếm .d.tscác tệp ở cùng một nơi mà nó sẽ tìm .tscác tệp bình thường : như "tệp" được chỉ định, "bao gồm" và "loại trừ" trong tsconfig.json. Tôi không khuyên bạn nên sử dụng typeRootscho mục đích này: đó là dành cho vị trí của các mô-đun loại bên ngoài (tức là node_modules/@types), không phải các .d.tstệp riêng lẻ .
Retsam

3
Tôi nhận được "tệp foo.d.ts không phải là mô-đun"
Nathan H

2
Dường như tệp ký tự đại diện này cần phải được gọi là "typings.d.ts"
jacob

4
Tôi nên đặt .d.tstập tin này ở đâu?
tonix

127

Nếu bạn cần khắc phục nhanh, chỉ cần thêm phần này trước dòng nhập của bạn:

// @ts-ignore

7
Cảm ơn, câu trả lời hữu ích nhất cho trường hợp của tôi.
David

Điều này gây ra lỗi trong các phiên bản sau của eslint:error Do not use "// @ts-ignore" comments because they suppress compilation errors @typescript-eslint/ban-ts-ignore
Hykilpikonna

91

Cảm giác đó khi bạn nhìn ra hai ngày và thấy nó như thế này: chỉ cần loại bỏ .jstừ "main": "dist/index.js"trong package.jsonvà mọi thứ hoạt động tốt!

"main": "dist/index",

CẬP NHẬT : câu trả lời này tương đối nếu bạn có gói npm của riêng bạn, nếu không - xem câu trả lời của tôi dưới đây .

Và nếu câu trả lời ở trên không được giải quyết, hãy nhập mô-đun của bạn, hãy thử chỉ cần thêm typingsvào package.json:

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

Tất nhiên, ở đây thư mục dist- đó là nơi lưu trữ các tập tin mô-đun của bạn.


Tôi đã đến câu hỏi của bạn và câu trả lời của bạn nhiều lần trong những ngày vừa qua và tôi muốn nói thêm rằng điều tôi thiếu là khai báo các loại đó trong tệp .d.ts, vì vậy, trong trường hợp của tôi, đã cài đặt các mô-đun nút mà không có các loại (và tôi không thể cài đặt giải thích các loại của chúng) bắt đầu hoạt động bằng cách khai báo chúng trong tệp đó bằng cách viết "khai báo mô-đun 'MYDesiredModule'
Juan

Cảm ơn. Thêm "typings": "dist / index", vào gói.json của tôi là những gì làm việc cho tôi. Kỳ lạ là Mã VS ném lỗi bản in khi tôi thậm chí không sử dụng
TypeScript

Cảm ơn bạn đã hiểu biết của bạn! Bạn có thể vui lòng cho tôi biết lý do tại sao các định nghĩa Mã VS không hoạt động cho gói npm của riêng tôi nếu tôi cố gắng đi đến các định nghĩa không? Tôi đã tạo một câu hỏi ở đây và không có may mắn cho đến nay ... stackoverflow.com/questions/59128917/
Mạnh

bạn cần thêm tệp "index.d.ts" vào thư mục dist và đặt declare module "moduleName" trong lúc này
Sunny Sun

42

TypeScript về cơ bản đang thực hiện các quy tắc và thêm các loại vào mã của bạn để làm cho nó rõ ràng và chính xác hơn do thiếu các ràng buộc trong Javascript. TypeScript yêu cầu bạn mô tả dữ liệu của mình để trình biên dịch có thể kiểm tra mã của bạn và tìm lỗi. Trình biên dịch sẽ cho bạn biết nếu bạn đang sử dụng các loại không khớp, nếu bạn ở ngoài phạm vi của mình hoặc bạn cố gắng trả về một loại khác. Vì vậy, khi bạn đang sử dụng các thư viện và mô-đun bên ngoài với TypeScript, chúng cần chứa các tệp mô tả các loại trong mã đó. Những tệp này được gọi là tệp khai báo kiểu có phần mở rộng d.ts. Hầu hết các loại khai báo cho các mô-đun npm đã được viết và bạn có thể bao gồm chúng bằng cách sử dụng npm install @types/module_name(trong đó module_name là tên của mô-đun có loại bạn muốn bao gồm).

Tuy nhiên, có những mô-đun không có định nghĩa loại của chúng và để khắc phục lỗi và nhập mô-đun bằng cách sử dụng import * as module_name from 'module-name', hãy tạo một thư mục typingstrong thư mục gốc của dự án của bạn, bên trong tạo một thư mục mới với tên mô-đun của bạn và trong đó thư mục tạo một module_name.d.tstập tin và viết declare module 'module_name'. Sau đó, chỉ cần đi đến tsconfig.jsontệp của bạn và thêm "typeRoots": [ "../../typings", "../../node_modules/@types"]vào compilerOptions(với đường dẫn tương đối phù hợp vào thư mục của bạn) để cho TypeScript biết nơi nó có thể tìm thấy các định nghĩa loại của thư viện và mô-đun của bạn và thêm thuộc tính mới "exclude": ["../../node_modules", "../../typings"]vào tệp. Dưới đây là một ví dụ về cách tệp tsconfig.json của bạn trông như thế nào:

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

Bằng cách này, lỗi sẽ biến mất và bạn sẽ có thể tuân theo các quy tắc ES6 và TypeScript mới nhất.


Nó chỉ làm việc cho tôi nếu tôi đặt tên cho các tập tin đánh máy index.d.ts. Ngoài ra, đây là giải pháp duy nhất phù hợp với tôi.
Chris Haines

21

Đối với bất kỳ ai khác đọc điều này, hãy thử đổi tên tệp .js của bạn thành .ts

Chỉnh sửa: Bạn cũng có thể thêm "allowJs": truevào tệp tsconfig.


yeah, có cùng một vấn đề với "Reac-fusioncharts" và giải pháp này hoạt động như một cơ duyên.
ngáp

16

Cách này hiệu quả với tôi:

1. thêm khai báo của riêng bạn vào một tệp khai báo, chẳng hạn như index.d.ts (có thể dưới gốc dự án)
declare module 'Injector';
2. thêm index.d.ts của bạn vào 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
    }

- chỉnh sửa: dấu ngoặc kép cần thiết xung quanh tên mô-đun


4

Tôi gặp vấn đề tương tự khi sử dụng mô-đun nút với ứng dụng phản ứng được viết bằng bản in. Các mô-đun đã được cài đặt thành công bằng cách sử dụng npm i --save my-module. Nó được viết bằng javascript và xuất một Clientlớp.

Với:

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

Quá trình biên dịch không thành công với lỗi:

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-modulekhông tồn tại, vì vậy tôi đã thêm một my-module.d.tstệp bên cạnh tệp my-moduleđược nhập, với dòng được đề xuất. Sau đó tôi đã nhận được lỗi:

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

Máy khách thực sự được xuất và hoạt động bình thường nếu tôi sử dụng nó trong ứng dụng js. Ngoài ra, thông báo trước cho tôi biết rằng trình biên dịch đang tìm trong tệp bên phải ( /node_modules/my-module/lib/index.jsđược xác định trong my-module/package.json "main"phần tử).

Tôi đã giải quyết vấn đề bằng cách nói với trình biên dịch mà tôi không quan tâm đến ẩn any, nghĩa là tôi đã đặt thành falsedòng sau của tsconfig.jsontệp:

    "noImplicitAny": false,

14
Ý tôi là, điều này hoạt động nhưng bạn đang mất khả năng nhập đúng phần còn lại của mã. Đó không phải là một cách giải quyết tuyệt vời.
phillyslick

3

đơn giản để khắc phục bạn là:

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

nếu bạn muốn khai báo giao diện của đối tượng (Đề xuất cho dự án lớn), bạn có thể sử dụng:

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

Làm thế nào để sử dụng nó? đơn giản..

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

2

Tôi cũng đã nhận được điều này, tôi đã gặp khó khăn trong một thời gian, ngay cả với mô-đun và các loại đã được cài đặt và tải lại IDE của tôi nhiều lần.

Điều đã khắc phục nó trong trường hợp của tôi là chấm dứt các quá trình đầu cuối, loại bỏ node_modules, xóa bộ đệm của trình quản lý gói nút và làm mới installsau đó tải lại trình soạn thảo.


2

Thật không may, nó nằm ngoài tầm tay của chúng tôi cho dù người viết gói có làm phiền với tệp khai báo hay không. Những gì tôi có xu hướng làm là có một tệp sao index.d.tscho chứa tất cả các tệp khai báo bị thiếu từ các gói khác nhau:

Chỉ mục:

declare module 'v-tooltip';
declare module 'parse5';
declare module 'emoji-mart-vue-fast';

0

Đây là những gì làm việc hình thành tôi.

npm install --save readline


0

Tôi đã thử mọi thứ ở đây, nhưng đối với tôi đó là một vấn đề hoàn toàn khác: tôi phải xóa khỏi *.d.tsmọi báo cáo nhập khẩu của mình:

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

Sau khi xóa lỗi, ...

Làm rõ : Khi chúng tôi khai báo một mô-đun trong một *.d.tstệp, nó sẽ tự động được trình biên dịch Typecript chọn làm mô-đun môi trường xung quanh (mô-đun bạn không cần nhập rõ ràng). Khi chúng tôi chỉ định import ... from ..., tệp bây giờ sẽ trở thành mô-đun (ES6) bình thường và do đó sẽ không được chọn tự động. Do đó, nếu bạn vẫn muốn nó hoạt động như một mô-đun xung quanh , hãy sử dụng kiểu nhập khác như vậy:

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

-4

Đơn giản là bạn có thể nhập nó bằng cách sử dụng mã yêu cầu như sau:

var _ = require('your_module_name');
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.