Nie można znaleźć pliku deklaracji dla modułu „nazwa-modułu”. „/path/to/module-name.js” niejawnie ma typ „dowolny”


303

Czytam, jak działa rozdzielczość modułu TypeScript .

Mam następujące repozytorium: @ ts-stack / di . Po skompilowaniu struktura katalogów wygląda następująco:

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

W moim pakiecie.json napisałem "main": "dist/index.js".

W Node.js wszystko działa dobrze, ale TypeScript:

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

Nie można znaleźć pliku deklaracji dla modułu „@ ts-stack / di”. „/path/to/node_modules/@ts-stack/di/dist/index.js” niejawnie ma typ „dowolny”.

A jednak, jeśli zaimportuję w następujący sposób, wszystko działa:

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

Co ja robię źle?

Odpowiedzi:


295

Oto dwa inne rozwiązania

Jeśli moduł nie jest twój - spróbuj zainstalować typy z @types:

npm install -D @types/module-name

Jeśli powyższe błędy instalacyjne - spróbuj zmienić importinstrukcje na require:

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

13
Jeśli nie możesz znaleźć nazwy, uruchom ją dla TypeScript 2.0:npm install @types/node --save-dev
Ogglas

120
Co jeśli moduł nie ma pakietu @types?
Daniel Kmak

37
Myślę, że używanie requirezamiast importjest trochę anty-wzorcem: lepiej zadeklarować moduł w .d.tspliku; zobacz moją odpowiedź poniżej.
Retsam

2
Przykładowe użycie: const mdbreact = require('mdbreact'); const { Button, Card, CardBody, CardText, CardTitle, CardImage } = mdbreact;
Sgedda,

1
To kiepska rada. To całkowicie neguje sens TypeScript i ogólne podejście FOSS, że „coś łatwego jest warte wniesienia wkładu”. Jeśli brakuje wpisywania a, poszukaj kogoś, kto to zrobił i nie opublikował lub nie przesyła dokumentu PR ze swoimi wpisaniami lub nie używa systemu pisania, jeśli chcesz go obejść.
Dave Mackintosh,

265

Jeśli importujesz moduł innej firmy 'foo', który nie zapewnia żadnych typów, ani w samej bibliotece, ani w @types/foopakiecie (generowanym z repozytorium DefinitelyTyped ), możesz usunąć ten błąd, deklarując moduł w pliku plik z .d.tsrozszerzeniem. TypeScript szuka .d.tsplików w tych samych miejscach, w których będzie szukać normalnych .tsplików: jak określono w „files”, „include” i „exclude” w tsconfig.json.

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

Następnie po zaimportowaniu foozostanie wpisany jako any.


Alternatywnie, jeśli chcesz rzutować własne pisma, możesz to zrobić również:

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

Wtedy to skompiluje się poprawnie:

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

Nie musisz podawać pełnych typów dla modułu, wystarczy dla bitów, których faktycznie używasz (i chcesz odpowiednich typów), więc jest to szczególnie łatwe, jeśli używasz dość niewielkiej ilości API.


Z drugiej strony, jeśli nie przejmujesz się typowaniem bibliotek zewnętrznych i chcesz importować wszystkie biblioteki bez typowania any, możesz dodać to do pliku z .d.tsrozszerzeniem:

declare module '*';

Zaletą (i minusem) tego jest to, że możesz importować absolutnie wszystko, a TS się skompiluje.


27
gdzie kompilator szuka d.tsplików? powinieneś podać jakąkolwiek konfigurację taką jak typeRoots?
Tom

17
@Tom Wyszukuje .d.tspliki w tych samych miejscach, w których będzie szukał normalnych .tsplików: jak określono „pliki”, „ dołącz ” i „wyklucz” w pliku tsconfig.json. Nie polecałbym używać typeRootsdo tego celu: jest to przeznaczone do lokalizacji modułów typu zewnętrznego (tj. node_modules/@types), A nie pojedynczych .d.tsplików.
Retsam,

3
Dostaję „plik foo.d.ts nie jest modułem”
Nathan H

2
Wygląda na to, że ten plik symboli wieloznacznych należy nazwać „typings.d.ts”
Jacob

4
Gdzie powinienem umieścić ten .d.tsplik?
tonix

127

Jeśli potrzebujesz szybkiej poprawki, po prostu dodaj ją przed linią importu:

// @ts-ignore

7
Dzięki, najbardziej przydatna odpowiedź w mojej sprawie.
David

Powoduje to błąd w późniejszych wersjach eslint:error Do not use "// @ts-ignore" comments because they suppress compilation errors @typescript-eslint/ban-ts-ignore
Hykilpikonna

91

To uczucie, gdy jesteś patrząc na dwa dni i znaleźć to tak: po prostu usunąć .jsz "main": "dist/index.js"w package.jsoni wszystko działa poprawnie!

"main": "dist/index",

UPD : ta odpowiedź względna, jeśli masz własny pakiet npm, jeśli nie - patrz moja odpowiedź poniżej .

A jeśli powyższa odpowiedź nie rozwiązany importu modułu, spróbuj po prostu dodać typingsw package.json:

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

Oczywiście tutaj folder dist- tam są przechowywane pliki modułu.


W ciągu ostatnich dni wielokrotnie podchodziłem do twojego pytania i odpowiedzi i chciałbym dodać, że brakowało mi zadeklarowania tych typów w pliku .d.ts, więc w moim przypadku zainstalowałem moduły węzłów, które były dostarczane bez typy (i nie byłem w stanie zainstalować Explicity ich typy) zaczęły działać, deklarując je w tym pliku, pisząc „zadeklaruj moduł„ MYDesiredModule ”
Juan

Dzięki. Dodanie „typings”: „dist / index” do mojego package.json było dla mnie skuteczne. Dziwne, że VS Code zgłasza błąd maszynopisu, gdy nawet nie używam TypeScript
wydzwaniają

Dziękujemy za wgląd! Czy możesz mi powiedzieć, dlaczego definicje VS Code nie działają dla mojego własnego pakietu npm, jeśli próbuję przejść do definicji? Stworzyłem tutaj pytanie i jak dotąd nie miałem szczęścia ... stackoverflow.com/questions/59128917/
tonix

musisz dodać plik „index.d.ts” do folderu dist i umieścić declare module "moduleName" w międzyczasie
Sunny Sun

42

TypeScript w zasadzie implementuje reguły i dodaje typy do twojego kodu, aby był bardziej przejrzysty i dokładny z powodu braku ograniczeń w JavaScript. TypeScript wymaga opisania danych, aby kompilator mógł sprawdzić kod i znaleźć błędy. Kompilator poinformuje Cię, jeśli używasz niedopasowanych typów, jeśli jesteś poza zasięgiem lub próbujesz zwrócić inny typ. Tak więc, gdy używasz zewnętrznych bibliotek i modułów z TypeScript, muszą one zawierać pliki opisujące typy w tym kodzie. Pliki te nazywane są plikami deklaracji typu z rozszerzeniem d.ts. Większość typów deklaracji dla modułów npm jest już napisanych i możesz je uwzględnić za pomocą npm install @types/module_name(gdzie nazwa_modułu to nazwa modułu, którego typy chcesz uwzględnić).

Istnieją jednak moduły, które nie mają definicji typów, i aby usunąć błąd i zaimportować moduł za pomocą import * as module_name from 'module-name', utwórz folder typingsw katalogu głównym projektu, w środku utwórz nowy folder z nazwą modułu i tym folder utwórz module_name.d.tsplik i zapisz declare module 'module_name'. Po to właśnie przejdź do tsconfig.jsonpliku i dodać "typeRoots": [ "../../typings", "../../node_modules/@types"]w compilerOptions(z właściwą ścieżkę względną do folderów), aby pozwolić maszynopis wie, gdzie można go znaleźć definicje typów bibliotek i modułów i dodać nową właściwość "exclude": ["../../node_modules", "../../typings"]do pliku. Oto przykład, jak powinien wyglądać plik tsconfig.json:

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

W ten sposób błąd zniknie i będziesz mógł trzymać się najnowszych reguł ES6 i TypeScript.


Działa to tylko dla mnie, jeśli nazwałem plik pisma index.d.ts. Poza tym było to jedyne rozwiązanie, które zadziałało dla mnie.
Chris Haines

21

Dla każdego, kto to czyta, spróbuj zmienić nazwę pliku .js na .ts

Edycja: Możesz także dodać "allowJs": truedo pliku tsconfig.


tak, miałem ten sam problem z „wykresami reakcji-reakcji” i to rozwiązanie działało jak urok.
yawningphantom

16

Ten sposób działa dla mnie:

1. dodaj własną deklarację do pliku deklaracji, takiego jak index.d.ts (może w katalogu głównym projektu)
declare module 'Injector';
2. dodaj plik index.d.ts do pliku 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
    }

- edycja: potrzebne cudzysłowy wokół nazwy modułu


4

Miałem ten sam problem z użyciem modułu węzła z aplikacją reagującą napisaną na maszynie. Moduł został pomyślnie zainstalowany przy użyciu npm i --save my-module. Jest napisany javascript i eksportuje Clientklasę.

Z:

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

Kompilacja kończy się niepowodzeniem z błędem:

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-modulenie istnieje, więc dodałem my-module.d.tsplik obok tego, do którego my-modulejest importowany, z sugerowaną linią. Wtedy dostałem błąd:

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

Klient jest faktycznie eksportowany i działa normalnie, jeśli użyję go w aplikacji js. Ponadto poprzedni komunikat mówi mi, że kompilator szuka odpowiedniego pliku ( /node_modules/my-module/lib/index.jsjest zdefiniowany w my-module/package.json "main"elemencie).

Rozwiązałem problem, mówiąc kompilatorowi, że nie dbam o niejawne any, to znaczy ustawiłem falsenastępujący wiersz tsconfig.jsonpliku:

    "noImplicitAny": false,

14
To znaczy, działa, ale tracisz możliwość ścisłego wpisywania reszty kodu. To nie jest świetne obejście.
phillyslick

3

prosty do naprawienia jest:

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

jeśli chcesz zadeklarować interfejs obiektu (Polecaj dla dużego projektu) możesz użyć:

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

Jak tego użyć? prosty..

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

2

Ja też to dostawałem, przez pewien czas byłem zdumiony, nawet gdy moduł i typy były już zainstalowane i kilkakrotnie ładowałem IDE.

W moim przypadku naprawiłem to, kończąc procesy terminalowe, usuwając node_modules, czyszcząc pamięć podręczną menedżera pakietów węzłów i robiąc nowe, installa następnie ponownie ładując edytor.


2

Niestety, nie jest w naszych rękach, czy twórca pakietu przeszkadza plikowi deklaracji. To, co zwykle robię, to taki plik, index.d.tsktóry będzie zawierał wszystkie brakujące pliki deklaracji z różnych pakietów:

Index.ts:

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


0

Próbowałem już wszystkiego tutaj, ale dla mnie był to zupełnie inny problem: musiałem usunąć z moich *.d.tswszelkich instrukcji importu:

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

Po usunięciu błędu zniknął ...

Wyjaśnienie : Kiedy deklarujemy moduł w *.d.tspliku, jest on automatycznie wybierany przez kompilator Typescript jako moduł otoczenia (ten, którego nie trzeba jawnie importować). Gdy określimy import ... from ..., plik staje się teraz normalnym modułem (ES6), a zatem nie zostanie pobrany automatycznie. Dlatego jeśli nadal chcesz, aby zachowywał się jak moduł otoczenia , użyj innego stylu importu, takiego jak:

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

-4

Po prostu możesz go zaimportować, używając następującego kodu:

var _ = require('your_module_name');
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.