Tidak dapat menemukan file pernyataan untuk 'modul-nama' modul. '/path/to/module-name.js' secara implisit memiliki tipe 'apa saja'

303

Saya membaca cara kerja resolusi modul TypeScript .

Saya memiliki repositori berikut: @ ts-stack / di . Setelah mengkompilasi struktur direktori adalah sebagai berikut:

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

Dalam package.json saya saya tulis "main": "dist/index.js".

Di Node.js semuanya berfungsi dengan baik, tetapi TypeScript:

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

Tidak dapat menemukan file deklarasi untuk modul '@ ts-stack / di'. '/path/to/node_modules/@ts-stack/di/dist/index.js' secara implisit memiliki tipe 'apa saja'.

Namun, jika saya mengimpor sebagai berikut, maka semuanya berfungsi:

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

Apa yang saya lakukan salah?

ktretyak
sumber

Jawaban:

295

Berikut ini dua solusi lain

Ketika modul bukan milik Anda - cobalah untuk menginstal jenis dari @types:

npm install -D @types/module-name

Jika kesalahan pemasangan di atas - coba ubah importpernyataan ke require:

// import * as yourModuleName from 'module-name';
const yourModuleName = require('module-name');
ktretyak
sumber
13
Jika Anda tidak dapat menemukan nama harus menjalankan ini untuk TypeScript 2.0:npm install @types/node --save-dev
Ogglas
120
Bagaimana jika modul tidak memiliki paket @types?
Daniel Kmak
37
Saya pikir menggunakan requirebukan importsedikit anti-pola: lebih baik mendeklarasikan modul dalam .d.tsfile; lihat jawaban saya di bawah ini.
Retsam
2
Contoh penggunaan: const mdbreact = require('mdbreact'); const { Button, Card, CardBody, CardText, CardTitle, CardImage } = mdbreact;
Sgedda
1
Ini saran yang buruk. Ini benar-benar meniadakan poin dari TypeScript dan sikap FOSS umum dari "sesuatu yang cukup mudah patut dikontribusikan". Jika ada yang kurang mengetik, cari seseorang telah melakukannya dan tidak menerbitkan atau mengirimkan PR dengan mengetik Anda atau tidak menggunakan sistem pengetikan jika Anda hanya ingin menghindarinya.
Dave Mackintosh
266

Jika Anda mengimpor modul pihak ketiga 'foo'yang tidak menyediakan pengetikan apa pun, baik di perpustakaan itu sendiri, atau dalam @types/foopaket (dihasilkan dari repositori DefinitelyTyped ), maka Anda dapat membuat kesalahan ini hilang dengan mendeklarasikan modul dalam file dengan .d.tsekstensi. TypeScript mencari .d.tsfile di tempat yang sama yang akan mencari .tsfile normal : seperti ditentukan dalam "file", "termasuk", dan "kecualikan" di tsconfig.json.

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

Kemudian ketika Anda mengimpornya foohanya akan diketik sebagai any.


Sebagai alternatif, jika Anda ingin menggulung ketikan Anda sendiri, Anda juga dapat melakukannya:

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

Maka ini akan dikompilasi dengan benar:

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

Anda tidak harus memberikan pengetikan penuh untuk modul, cukup untuk bit yang sebenarnya Anda gunakan (dan ingin pengetikan yang tepat), jadi itu sangat mudah dilakukan jika Anda menggunakan API dalam jumlah yang cukup kecil.


Di sisi lain, jika Anda tidak peduli tentang pengetikan pustaka eksternal dan ingin semua pustaka tanpa pengetikan diimpor any, Anda dapat menambahkan ini ke file dengan .d.tsekstensi:

declare module '*';

Keuntungan (dan kerugian) dari ini adalah Anda dapat mengimpor apa saja dan TS akan dikompilasi.

Retsam
sumber
27
di mana kompiler mencari d.tsfile? Anda harus memberikan konfigurasi seperti apa typeRoots?
Tom
17
@ Tom Mencari .d.tsfile di tempat yang sama dengan mencari .tsfile normal : seperti yang ditentukan "file", "termasuk", dan "mengecualikan" di tsconfig.json. Saya tidak akan merekomendasikan menggunakan typeRootsuntuk tujuan ini: itu dimaksudkan untuk lokasi modul tipe eksternal (yaitu node_modules/@types), bukan .d.tsfile individual .
Retsam
3
Saya mendapatkan "file foo.d.ts bukan modul"
Nathan H
2
Sepertinya file wildcard ini perlu disebut "typings.d.ts"
jacob
4
Di mana saya harus meletakkan .d.tsfile ini ?
tonix
127

Jika Anda perlu perbaikan cepat, cukup tambahkan ini sebelum baris impor Anda:

// @ts-ignore
Liran H
sumber
7
Terima kasih, jawaban paling berguna untuk kasus saya.
David
Ini menyebabkan kesalahan pada versi eslint yang lebih baru:error Do not use "// @ts-ignore" comments because they suppress compilation errors @typescript-eslint/ban-ts-ignore
Hykilpikonna
91

Perasaan itu ketika Anda melihat keluar selama dua hari dan menemukannya seperti ini: cukup hapus .jsdari "main": "dist/index.js"dalam package.jsondan semuanya bekerja dengan baik!

"main": "dist/index",

UPD : jawaban ini relatif jika Anda memiliki paket npm Anda sendiri, jika tidak - lihat jawaban saya di bawah ini .

Dan jika jawaban di atas tidak diselesaikan impor modul Anda, coba tambahkan saja typingsdi package.json:

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

Tentu saja, di sini folder dist- ini tempat menyimpan file modul Anda.

ktretyak
sumber
Saya datang ke pertanyaan dan jawaban Anda berkali-kali pada hari-hari terakhir ini dan saya ingin menambahkan bahwa apa yang saya lewatkan adalah mendeklarasikan tipe-tipe itu dalam file .d.ts, jadi, dalam kasus saya, instal modul simpul yang datang tanpa types (dan saya tidak dapat menginstal explicity tipe mereka) mulai bekerja dengan mendeklarasikannya dalam file itu dengan menulis "menyatakan modul 'MYDesiredModule'
Juan
Terima kasih. Menambahkan "typings": "dist / index", ke package.json saya adalah yang bekerja untuk saya. Aneh bahwa VS Code melempar kesalahan naskah ketika saya bahkan tidak menggunakan TypeScript
phocks
Terima kasih atas wawasan Anda! Bisakah Anda memberi tahu saya mengapa definisi Kode VS tidak berfungsi untuk paket npm saya sendiri jika saya mencoba untuk pergi ke definisi? Saya telah membuat pertanyaan di sini dan sejauh ini tidak berhasil ... stackoverflow.com/questions/59128917/…
tonix
Anda perlu menambahkan file "index.d.ts" di folder dist dan masukkan declare module "moduleName" sementara itu
Sunny Sun
42

TypeScript pada dasarnya menerapkan aturan dan menambahkan tipe ke kode Anda untuk membuatnya lebih jelas dan lebih akurat karena kurangnya kendala dalam Javascript. TypeScript mengharuskan Anda untuk menggambarkan data Anda, sehingga kompiler dapat memeriksa kode Anda dan menemukan kesalahan. Kompiler akan memberi tahu Anda jika Anda menggunakan tipe yang tidak cocok, jika Anda berada di luar jangkauan Anda atau Anda mencoba mengembalikan tipe yang berbeda. Jadi, ketika Anda menggunakan pustaka dan modul eksternal dengan TypeScript, mereka harus berisi file yang menjelaskan tipe dalam kode itu. File-file itu disebut jenis file pernyataan dengan ekstensi d.ts. Sebagian besar tipe deklarasi untuk modul npm sudah ditulis dan Anda dapat memasukkannya menggunakan npm install @types/module_name(di mana module_name adalah nama modul yang jenisnya ingin Anda sertakan).

Namun, ada modul yang tidak memiliki definisi tipenya dan untuk membuat kesalahan hilang dan mengimpor modul menggunakan import * as module_name from 'module-name', buat folder typingsdi root proyek Anda, di dalam buat folder baru dengan nama modul Anda dan di dalamnya folder buat module_name.d.tsfile dan tulis declare module 'module_name'. Setelah ini hanya pergi ke Anda tsconfig.jsonberkas dan menambahkan "typeRoots": [ "../../typings", "../../node_modules/@types"]dalam compilerOptions(dengan path relatif tepat untuk folder Anda) untuk membiarkan naskah tahu di mana ia dapat menemukan jenis definisi perpustakaan dan modul dan menambahkan properti baru "exclude": ["../../node_modules", "../../typings"]untuk file. Berikut ini adalah contoh tampilan file tsconfig.json Anda:

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

Dengan melakukan ini, kesalahan akan hilang dan Anda akan dapat tetap berpegang pada aturan ES6 dan TypeScript terbaru.

Marko Rochevski
sumber
Itu hanya bekerja untuk saya jika saya memberi nama file pengetikan index.d.ts. Selain itu, ini adalah satu-satunya solusi yang bekerja untuk saya.
Chris Haines
21

Untuk orang lain yang membaca ini, coba ganti nama file .js Anda menjadi .ts

Sunting: Anda juga dapat menambahkan "allowJs": trueke file tsconfig Anda.

Martin Lockett
sumber
ya, punya masalah yang sama dengan "react-fusioncharts" dan solusi ini bekerja seperti pesona.
yawningphantom
16

Cara ini bekerja untuk saya:

1. tambahkan deklarasi Anda sendiri dalam file deklarasi seperti index.d.ts (mungkin di bawah root proyek)
declare module 'Injector';
2. tambahkan index.d.ts Anda ke 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
    }

- edit: tanda kutip yang diperlukan di sekitar nama modul

Lumaskete
sumber
4

Saya memiliki masalah yang sama menggunakan modul simpul dengan aplikasi reaksi yang ditulis dalam naskah. Modul berhasil diinstal menggunakan npm i --save my-module. Itu ditulis dalam javascript dan mengekspor Clientkelas.

Dengan:

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

Kompilasi gagal dengan kesalahan:

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-moduletidak ada, jadi saya menambahkan my-module.d.tsfile di sebelah yang my-modulediimpor, dengan baris yang disarankan. Saya kemudian mendapatkan kesalahan:

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

Klien sebenarnya diekspor dan berfungsi normal jika saya menggunakannya di aplikasi js. Juga, pesan sebelumnya memberi tahu saya bahwa kompiler mencari di file yang tepat ( /node_modules/my-module/lib/index.jsdidefinisikan dalam my-module/package.json "main"elemen).

Saya memecahkan masalah dengan mengatakan kepada kompiler saya tidak peduli tentang implisit any, yaitu, saya mengatur ke falsebaris berikut dari tsconfig.jsonfile:

    "noImplicitAny": false,
Kanthavel
sumber
14
Maksud saya, ini berfungsi tetapi Anda kehilangan kemampuan untuk secara ketat mengetik sisa kode Anda. Ini bukan solusi yang bagus.
phillyslick
3

sederhana untuk memperbaiki Anda adalah:

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

jika Anda ingin mendeklarasikan antarmuka objek (Merekomendasikan untuk proyek besar) Anda dapat menggunakan:

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

Bagaimana cara menggunakannya? sederhana..

const x = require('foo') // or import x from 'foo'
x.getName() // intellisense can read this
Abdul Aziz Al Basyir
sumber
2

Saya mendapatkan ini juga, membuat saya bingung untuk sementara waktu, bahkan dengan modul dan tipe yang sudah diinstal dan memuat ulang IDE saya beberapa kali.

Apa yang diperbaiki dalam kasus saya adalah menghentikan proses terminal, menghapus node_modules, menghapus cache manajer paket node dan melakukan yang baru installkemudian memuat ulang editor.

Leo
sumber
2

Sayangnya itu di luar tangan kami apakah penulis paket mengganggu dengan file deklarasi. Apa yang cenderung saya lakukan adalah memiliki file index.d.tsyang berisi semua file deklarasi yang hilang dari berbagai paket:

Index.ts:

declare module 'v-tooltip';
declare module 'parse5';
declare module 'emoji-mart-vue-fast';
Luke Garrigan
sumber
0

Inilah yang berhasil membentuk saya.

npm install --save readline

klakson
sumber
0

Saya sudah mencoba semuanya di sini, tetapi bagi saya itu adalah masalah yang sama sekali berbeda: Saya harus menghapus dari *.d.tssemua pernyataan impor saya :

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

Setelah menghapus kesalahan hilang ...

Klarifikasi : Ketika kami mendeklarasikan modul dalam *.d.tsfile, itu secara otomatis diambil oleh kompiler Typecript sebagai modul ambient (yang Anda tidak perlu mengimpor secara eksplisit). Setelah kita tentukan import ... from ..., file sekarang menjadi modul normal (ES6), dan karenanya tidak akan diambil secara otomatis. Karenanya jika Anda tetap ingin berperilaku sebagai modul ambient , gunakan gaya impor yang berbeda seperti:

type MyType: import('3rd-party-module').SomeModuleType;
Ilyas Assainov
sumber
-4

Cukup Anda dapat mengimpornya menggunakan kode sebagai berikut:

var _ = require('your_module_name');
Riyad Khalifeh
sumber