Es konnte keine Deklarationsdatei für das Modul 'Modulname' gefunden werden. '/path/to/module-name.js' hat implizit einen 'any'-Typ

303

Ich habe gelesen, wie die Auflösung des TypeScript- Moduls funktioniert.

Ich habe das folgende Repository: @ ts-stack / di . Nach dem Kompilieren lautet die Verzeichnisstruktur wie folgt:

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

In meine package.json habe ich geschrieben "main": "dist/index.js".

In Node.js funktioniert alles gut, aber TypeScript:

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

Es konnte keine Deklarationsdatei für das Modul '@ ts-stack / di' gefunden werden. '/path/to/node_modules/@ts-stack/di/dist/index.js' hat implizit einen 'any'-Typ.

Und doch, wenn ich wie folgt importiere, dann funktioniert alles:

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

Was mache ich falsch?

ktretyak
quelle

Antworten:

295

Hier sind zwei weitere Lösungen

Wenn ein Modul nicht Ihnen gehört, versuchen Sie, Typen zu installieren von @types:

npm install -D @types/module-name

Wenn die oben genannten Installationsfehler auftreten, ändern Sie die importAnweisungen in require:

// import * as yourModuleName from 'module-name';
const yourModuleName = require('module-name');
ktretyak
quelle
13
Wenn Sie keinen Namen finden konnten, führen Sie diesen für TypeScript 2.0 aus:npm install @types/node --save-dev
Ogglas
120
Was ist, wenn das Modul kein @ types-Paket hat?
Daniel Kmak
37
Ich denke, die Verwendung von requireanstelle von importist ein bisschen ein Anti-Pattern: Es ist besser, das Modul in einer .d.tsDatei zu deklarieren . siehe meine Antwort unten.
Retsam
2
Anwendungsbeispiel: const mdbreact = require('mdbreact'); const { Button, Card, CardBody, CardText, CardTitle, CardImage } = mdbreact;
Sgedda
1
Das ist ein schlechter Rat. Dies negiert völlig den Punkt von TypeScript und die allgemeine FOSS-Haltung von "etwas, das einfach genug ist, ist es wert, einen Beitrag zu leisten". Wenn eine Eingabe fehlt, hat die Suche nach jemandem dies getan und nicht veröffentlicht oder eine PR mit Ihren Eingaben eingereicht, oder Sie verwenden kein Schreibsystem, wenn Sie es nur umgehen möchten.
Dave Mackintosh
265

Wenn Sie ein Modul eines Drittanbieters 'foo'importieren, das weder in der Bibliothek selbst noch im @types/fooPaket (generiert aus dem DefinitelyTyped- Repository) Typisierungen bereitstellt, können Sie diesen Fehler beheben, indem Sie das Modul in a deklarieren Datei mit einer .d.tsErweiterung. TypeScript sucht .d.tsan denselben Stellen nach .tsDateien wie nach normalen Dateien: wie unter "Dateien", "Einschließen" und "Ausschließen" in der Datei angegeben tsconfig.json.

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

Wenn Sie dann importieren, wird fooes einfach als eingegeben any.


Wenn Sie Ihre eigenen Eingaben rollen möchten, können Sie dies auch tun:

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

Dann wird dies korrekt kompiliert:

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

Sie müssen keine vollständigen Typisierungen für das Modul bereitstellen, gerade genug für die Bits, die Sie tatsächlich verwenden (und für die Sie die richtigen Typisierungen wünschen). Dies ist besonders einfach, wenn Sie eine relativ kleine Menge an API verwenden.


Wenn Sie sich jedoch nicht für die Typisierung externer Bibliotheken interessieren und möchten, dass alle Bibliotheken ohne Typisierung als importiert werden any, können Sie dies einer Datei mit der folgenden .d.tsErweiterung hinzufügen :

declare module '*';

Der Vorteil (und Nachteil) davon ist, dass Sie absolut alles importieren können und TS kompiliert.

Retsam
quelle
27
Wo sucht der Compiler nach d.tsDateien? sollten Sie eine Konfiguration wie bereitstellen typeRoots?
Tom
17
@Tom Es sucht nach .d.tsDateien an den gleichen Stellen wie nach normalen .tsDateien: wie angegeben "Dateien", "Einschließen" und "Ausschließen" in der tsconfig.json. Ich würde die Verwendung typeRootsfür diesen Zweck nicht empfehlen : Dies ist für den Speicherort externer Typmodule (dh node_modules/@types) vorgesehen, nicht für einzelne .d.tsDateien.
Retsam
3
Ich bekomme "Datei foo.d.ts ist kein Modul"
Nathan H
2
Es sieht so aus, als müsste diese Platzhalterdatei "typings.d.ts" heißen
Jacob
4
Wo soll ich diese .d.tsDatei ablegen?
Tonix
127

Wenn Sie eine schnelle Lösung benötigen, fügen Sie diese einfach vor der Zeile Ihres Imports hinzu:

// @ts-ignore
Liran H.
quelle
7
Danke, nützlichste Antwort für meinen Fall.
David
Dies führt in späteren Versionen von eslint zu einem Fehler:error Do not use "// @ts-ignore" comments because they suppress compilation errors @typescript-eslint/ban-ts-ignore
Hykilpikonna
91

Das Gefühl , wenn man zwei Tage lang suchen und es so finden: einfach entfernen .jsaus "main": "dist/index.js"in package.jsonund alles funktioniert!

"main": "dist/index",

UPD : Diese Antwort ist relativ, wenn Sie Ihr eigenes npm-Paket haben, wenn nicht - siehe meine Antwort unten .

Und wenn oben genannte Antwort nicht importieren Ihr Modul behoben, versuchen Sie fügen Sie einfach typingsin package.json:

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

Natürlich hier Ordner dist- hier werden die Dateien Ihres Moduls gespeichert.

ktretyak
quelle
Ich bin in den letzten Tagen viele Male auf Ihre Frage und Ihre Antwort gekommen, und ich möchte hinzufügen, dass ich diese Typen in einer .d.ts-Datei deklariert habe, also in meinem Fall Knotenmodule installiert habe, die ohne geliefert wurden Typen (und ich konnte explizit ihre Typen nicht installieren) begannen zu arbeiten, indem sie sie in dieser Datei deklarierten, indem sie "Deklarationsmodul 'MYDesiredModule'
Juan
Vielen Dank. Das Hinzufügen von "typings": "dist / index" zu meinem package.json hat bei mir funktioniert. Seltsam, dass VS Code einen Typoskriptfehler
auslöst,
Vielen Dank für Ihren Einblick! Können Sie mir bitte sagen, warum VS-Code-Definitionen für mein eigenes npm-Paket nicht funktionieren, wenn ich versuche, zu den Definitionen zu wechseln? Ich habe hier eine Frage erstellt und hatte bisher kein Glück ... stackoverflow.com/questions/59128917/…
tonix
Sie müssen die Datei "index.d.ts" im Ordner dist hinzufügen und declare module "moduleName" in der Zwischenzeit einfügen
Sunny Sun
42

TypeScript implementiert im Wesentlichen Regeln und fügt Ihrem Code Typen hinzu, um ihn klarer und genauer zu machen, da in Javascript keine Einschränkungen bestehen. Bei TypeScript müssen Sie Ihre Daten beschreiben, damit der Compiler Ihren Code überprüfen und Fehler finden kann. Der Compiler informiert Sie, wenn Sie nicht übereinstimmende Typen verwenden, wenn Sie sich außerhalb Ihres Gültigkeitsbereichs befinden oder wenn Sie versuchen, einen anderen Typ zurückzugeben. Wenn Sie externe Bibliotheken und Module mit TypeScript verwenden, müssen diese Dateien enthalten, die die Typen in diesem Code beschreiben. Diese Dateien werden als Typdeklarationsdateien mit einer Erweiterung bezeichnet d.ts. Die meisten Deklarationstypen für npm-Module sind bereits geschrieben und können mit verwendet werden npm install @types/module_name(wobei module_name der Name des Moduls ist, dessen Typen Sie einschließen möchten).

Es gibt jedoch Module, deren Typdefinitionen nicht vorhanden sind. Um den Fehler zu beheben und das Modul mithilfe von zu importieren import * as module_name from 'module-name', erstellen Sie einen Ordner typingsim Stammverzeichnis Ihres Projekts, erstellen Sie einen neuen Ordner mit Ihrem Modulnamen und darin Ordner eine module_name.d.tsDatei erstellen und schreiben declare module 'module_name'. Gehen Sie danach einfach zu Ihrer tsconfig.jsonDatei und fügen Sie "typeRoots": [ "../../typings", "../../node_modules/@types"]das hinzu compilerOptions(mit dem richtigen relativen Pfad zu Ihren Ordnern), um TypeScript mitzuteilen, wo es die Typdefinitionen Ihrer Bibliotheken und Module finden kann, und fügen Sie "exclude": ["../../node_modules", "../../typings"]der Datei eine neue Eigenschaft hinzu . Hier ist ein Beispiel, wie Ihre tsconfig.json-Datei aussehen sollte:

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

Auf diese Weise wird der Fehler behoben und Sie können sich an die neuesten ES6- und TypeScript-Regeln halten.

Marko Rochevski
quelle
Es hat bei mir nur funktioniert, wenn ich die Schreibdatei benannt habe index.d.ts. Davon abgesehen war dies die einzige Lösung, die für mich rundum funktionierte.
Chris Haines
21

Versuchen Sie für alle anderen, die dies lesen, Ihre .js-Datei in .ts umzubenennen

Bearbeiten: Sie können auch "allowJs": truezu Ihrer tsconfig-Datei hinzufügen .

Martin Lockett
quelle
Ja, hatte das gleiche Problem mit "React-Fusioncharts" und diese Lösung funktionierte wie ein Zauber.
Gähnenphantom
16

Dieser Weg funktioniert bei mir:

1. Fügen Sie Ihre eigene Deklaration in eine Deklarationsdatei wie index.d.ts ein (möglicherweise unter dem Projektstamm).
declare module 'Injector';
2. Fügen Sie Ihre index.d.ts zu tsconfig.json hinzu
  {
    "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: benötigte Anführungszeichen um den Modulnamen

Lumaskcete
quelle
4

Ich hatte das gleiche Problem bei der Verwendung eines Knotenmoduls mit einer in Typoskript geschriebenen Reaktionsanwendung. Das Modul wurde erfolgreich mit installiert npm i --save my-module. Es ist in Javascript geschrieben und exportiert eine ClientKlasse.

Mit:

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

Die Kompilierung schlägt mit dem Fehler fehl:

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-moduleexistiert nicht, daher habe ich my-module.d.tsneben der Datei, in die my-moduleimportiert wird, eine Datei mit der vorgeschlagenen Zeile hinzugefügt . Ich habe dann den Fehler bekommen:

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

Der Client wird tatsächlich exportiert und funktioniert normal, wenn ich ihn in einer js-App verwende. Außerdem sagt mir die vorherige Nachricht, dass der Compiler in der richtigen Datei sucht ( /node_modules/my-module/lib/index.jswird im my-module/package.json "main"Element definiert ).

Ich habe das Problem gelöst, indem ich dem Compiler mitgeteilt habe any, dass implizite Dinge mir egal sind, dh ich habe falsedie folgende Zeile der tsconfig.jsonDatei festgelegt:

    "noImplicitAny": false,
Kanthavel
quelle
14
Ich meine, das funktioniert, aber Sie verlieren die Fähigkeit, den Rest Ihres Codes streng einzugeben. Es ist keine gute Lösung.
Phillyslick
3

Einfach zu beheben ist:

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

Wenn Sie die Schnittstelle des Objekts deklarieren möchten (Empfehlung für großes Projekt), können Sie Folgendes verwenden:

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

Wie benutzt man das? einfach..

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

Ich bekam das auch, hatte mich eine Weile verwirrt, selbst wenn das Modul und die Typen bereits installiert waren und meine IDE mehrmals neu geladen wurden.

In meinem Fall wurde das Problem behoben, indem Terminalprozesse beendet, entfernt node_modules, der Cache des Node Package Managers geleert und installder Editor neu geladen wurde.

Löwe
quelle
2

Leider liegt es nicht in unserer Hand, ob der Paketschreiber mit einer Deklarationsdatei stört. Ich neige dazu, eine Datei zu haben index.d.ts, die alle fehlenden Deklarationsdateien aus verschiedenen Paketen enthält:

Index.ts:

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

Das hat bei mir funktioniert.

npm install --save readline

Honkskillet
quelle
0

Ich habe hier alles versucht, aber für mich war es ein ganz anderes Problem: Ich musste *.d.tsalle Importanweisungen entfernen :

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

Nach dem Entfernen des Fehlers ging weg ...

Erläuterung : Wenn wir ein Modul in einer *.d.tsDatei deklarieren , wird es vom Typescript-Compiler automatisch als Umgebungsmodul übernommen (das Sie nicht explizit importieren müssen). Sobald wir das angegeben haben import ... from ..., wird die Datei nun zu einem normalen (ES6) Modul und wird daher nicht automatisch aufgenommen. Wenn Sie also weiterhin möchten, dass es sich wie ein Umgebungsmodul verhält , verwenden Sie einen anderen Importstil wie folgt :

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

Sie können es einfach mit dem folgenden Code importieren:

var _ = require('your_module_name');
Riad Khalifeh
quelle