Impossible de trouver un fichier de déclaration pour le module 'nom-module'. '/path/to/module-name.js' a implicitement un type 'any'

303

J'ai lu comment fonctionne la résolution du module TypeScript .

J'ai le référentiel suivant: @ ts-stack / di . Après avoir compilé la structure du répertoire est la suivante:

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

Dans mon package.json, j'ai écrit "main": "dist/index.js".

Dans Node.js, tout fonctionne bien, mais TypeScript:

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

Impossible de trouver un fichier de déclaration pour le module '@ ts-stack / di'. '/path/to/node_modules/@ts-stack/di/dist/index.js' a implicitement un type 'any'.

Et pourtant, si j'importe comme suit, alors tout fonctionne:

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

Qu'est-ce que je fais mal?

ktretyak
la source

Réponses:

295

Voici deux autres solutions

Lorsqu'un module n'est pas le vôtre, essayez d'installer des types à partir de @types:

npm install -D @types/module-name

Si les erreurs d'installation ci-dessus - essayez de changer les importinstructions pour require:

// import * as yourModuleName from 'module-name';
const yourModuleName = require('module-name');
ktretyak
la source
13
Si vous ne parvenez pas à trouver le nom, exécutez ceci pour TypeScript 2.0:npm install @types/node --save-dev
Ogglas
120
Que faire si le module n'a pas de package @types?
Daniel Kmak
37
Je pense qu'utiliser à la requireplace de importest un peu anti-pattern: il vaut mieux déclarer le module dans un .d.tsfichier; voir ma réponse ci-dessous.
Retsam
2
Exemple d'utilisation: const mdbreact = require('mdbreact'); const { Button, Card, CardBody, CardText, CardTitle, CardImage } = mdbreact;
Sgedda
1
C'est un mauvais conseil. Cela nie totalement l'intérêt de TypeScript et l'attitude générale du SSOBL de "quelque chose d'assez facile mérite d'être contribué". S'il manque de taper a, la recherche de quelqu'un l'a fait et n'a pas publié ou soumis un PR avec vos dactylographies ou n'utilisez pas un système de dactylographie si vous voulez juste le contourner.
Dave Mackintosh
266

Si vous importez un module tiers 'foo'qui ne fournit aucune saisie, ni dans la bibliothèque elle-même, ni dans le @types/foopackage (généré à partir du référentiel DefinitelyTyped ), vous pouvez faire disparaître cette erreur en déclarant le module dans un fichier avec une .d.tsextension. TypeScript recherche les .d.tsfichiers aux mêmes endroits qu'il recherchera les .tsfichiers normaux : comme spécifié sous "fichiers", "inclure" et "exclure" dans le tsconfig.json.

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

Ensuite, lorsque vous importez, fooil sera simplement saisi comme any.


Alternativement, si vous voulez rouler vos propres dactylographies, vous pouvez aussi le faire:

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

Ensuite, cela se compilera correctement:

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

Vous n'avez pas à fournir des typages complets pour le module, juste assez pour les bits que vous utilisez réellement (et souhaitez des typages appropriés), il est donc particulièrement facile de le faire si vous utilisez une assez petite quantité d'API.


D'un autre côté, si vous ne vous souciez pas des typages des bibliothèques externes et souhaitez que toutes les bibliothèques sans typage soient importées en tant que any, vous pouvez l'ajouter à un fichier avec une .d.tsextension:

declare module '*';

L'avantage (et l'inconvénient) de cela est que vous pouvez importer n'importe quoi et que TS compilera.

Retsam
la source
27
où le compilateur recherche- d.tst-il les fichiers? devez-vous fournir une configuration telle que typeRoots?
Tom
17
@Tom Il recherche des .d.tsfichiers aux mêmes endroits qu'il recherchera des .tsfichiers normaux : comme spécifié "fichiers", "inclure" et "exclure" dans le tsconfig.json. Je ne recommanderais pas d'utiliser typeRootsà cet effet: c'est destiné à l'emplacement des modules de type externe (c'est-à-dire node_modules/@types), pas des .d.tsfichiers individuels .
Retsam
3
Je reçois "le fichier foo.d.ts n'est pas un module"
Nathan H
2
Il semble que ce fichier générique doive être appelé "typings.d.ts"
jacob
4
Où dois-je mettre ce .d.tsfichier?
tonix
127

Si vous avez besoin d'une solution rapide, ajoutez-la simplement avant la ligne de votre importation:

// @ts-ignore
Liran H
la source
7
Merci, la réponse la plus utile pour mon cas.
David
Cela provoque une erreur dans les versions ultérieures d'eslint:error Do not use "// @ts-ignore" comments because they suppress compilation errors @typescript-eslint/ban-ts-ignore
Hykilpikonna
91

Ce sentiment quand vous êtes à la recherche pendant deux jours et trouvez comme ceci: il suffit de retirer .jsde "main": "dist/index.js"dans package.jsonet tout fonctionne bien!

"main": "dist/index",

UPD : cette réponse est relative si vous avez votre propre package npm, sinon - voir ma réponse ci-dessous .

Et si la réponse ci - dessus pas résolu l' importation de votre module, essayez d' ajouter typingsdans package.json:

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

Bien sûr, ici le dossier dist- c'est où stocke les fichiers de votre module.

ktretyak
la source
Je suis venu à votre question et à votre réponse plusieurs fois ces derniers jours et j'aimerais ajouter que ce qui me manquait était de déclarer ces types dans un fichier .d.ts, donc, dans mon cas, des modules de nœuds installés sans types (et je n'ai pas pu installer explicitement leurs types) ont commencé à fonctionner en les déclarant dans ce fichier en écrivant "declare module 'MYDesiredModule'
Juan
Merci. Ajouter "typings": "dist / index" à mon package.json a été ce qui a fonctionné pour moi. Étrange que VS Code génère une erreur de frappe lorsque je n'utilise même pas TypeScript
phocks
Merci pour votre perspicacité! Pourriez-vous me dire pourquoi les définitions de code VS ne fonctionnent pas pour mon propre package npm si j'essaie d'accéder aux définitions? J'ai créé une question ici et je n'ai pas eu de chance jusqu'à présent ... stackoverflow.com/questions/59128917/…
tonix
vous devez ajouter le fichier "index.d.ts" dans le dossier dist et le mettre declare module "moduleName" en attendant
Sunny Sun
42

TypeScript implémente essentiellement des règles et ajoute des types à votre code pour le rendre plus clair et plus précis en raison de l'absence de contraintes dans Javascript. TypeScript vous oblige à décrire vos données, afin que le compilateur puisse vérifier votre code et trouver des erreurs. Le compilateur vous indiquera si vous utilisez des types incompatibles, si vous êtes hors de votre portée ou si vous essayez de renvoyer un type différent. Ainsi, lorsque vous utilisez des bibliothèques et des modules externes avec TypeScript, ils doivent contenir des fichiers décrivant les types de ce code. Ces fichiers sont appelés fichiers de déclaration de type avec une extension d.ts. La plupart des types de déclaration pour les modules npm sont déjà écrits et vous pouvez les inclure en utilisant npm install @types/module_name(où nom_module est le nom du module dont vous voulez inclure les types).

Cependant, il existe des modules qui n'ont pas leurs définitions de type et afin de faire disparaître l'erreur et d'importer le module en utilisant import * as module_name from 'module-name', créez un dossier typingsà la racine de votre projet, à l'intérieur créez un nouveau dossier avec le nom de votre module et dans ce dossier créer un module_name.d.tsfichier et écrire declare module 'module_name'. Après cela, allez simplement dans votre tsconfig.jsonfichier et ajoutez- "typeRoots": [ "../../typings", "../../node_modules/@types"]le compilerOptions(avec le chemin d'accès approprié à vos dossiers) pour indiquer à TypeScript où il peut trouver les définitions de types de vos bibliothèques et modules et ajouter une nouvelle propriété "exclude": ["../../node_modules", "../../typings"]au fichier. Voici un exemple de l'apparence de votre fichier tsconfig.json:

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

Ce faisant, l'erreur disparaîtra et vous pourrez vous en tenir aux dernières règles ES6 et TypeScript.

Marko Rochevski
la source
Cela ne fonctionnait pour moi que si je nommais le fichier de dactylographie index.d.ts. En dehors de cela, c'était la seule solution qui fonctionnait parfaitement pour moi.
Chris Haines
21

Pour toute autre personne lisant ceci, essayez de renommer votre fichier .js en .ts

Modifier: vous pouvez également ajouter "allowJs": trueà votre fichier tsconfig.

Martin Lockett
la source
oui, eu le même problème avec "react-fusioncharts" et cette solution a fonctionné comme un charme.
yawningphantom
16

Cela fonctionne pour moi:

1. ajoutez votre propre déclaration dans un fichier de déclaration tel que index.d.ts (peut-être sous la racine du projet)
declare module 'Injector';
2. ajoutez votre 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
    }

- modifier: les guillemets nécessaires autour du nom du module

Lumaskcete
la source
4

J'ai eu le même problème en utilisant un module de noeud avec une application de réaction écrite en tapuscrit. Le module a été installé avec succès à l'aide de npm i --save my-module. Il est écrit en javascript et exporte une Clientclasse.

Avec:

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

La compilation échoue avec l'erreur:

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-modulen'existe pas, j'ai donc ajouté un my-module.d.tsfichier à côté de celui où my-moduleest importé, avec la ligne suggérée. J'ai alors eu l'erreur:

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

Le client est en fait exporté et fonctionne normalement si je l'utilise dans une application js. En outre, le message précédent m'indique que le compilateur recherche dans le bon fichier ( /node_modules/my-module/lib/index.jsest défini dans l' my-module/package.json "main"élément).

J'ai résolu le problème en disant au compilateur que je m'en fichais implicitement any, c'est-à-dire que je définissais falsela ligne suivante du tsconfig.jsonfichier:

    "noImplicitAny": false,
Kanthavel
la source
14
Je veux dire, cela fonctionne mais vous perdez la possibilité de taper strictement le reste de votre code. Ce n'est pas une excellente solution de contournement.
phillyslick
3

simple à réparer est:

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

si vous voulez déclarer l'interface d'objet (recommandé pour un grand projet) vous pouvez utiliser:

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

Comment l'utiliser? Facile..

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

J'obtenais cela aussi, m'avait dérouté pendant un certain temps, même avec le module et les types déjà installés et en rechargeant plusieurs fois mon IDE.

Dans mon cas, ce qui a résolu le problème était de mettre fin aux processus terminaux, de supprimer node_modules, de vider le cache du gestionnaire de packages de nœuds et de faire un nouveau installchargement, puis de recharger l'éditeur.

Leo
la source
2

Malheureusement, il n'est pas de notre ressort si l'auteur du paquet dérange avec un fichier de déclaration. Ce que j'ai tendance à faire, c'est d'avoir un fichier index.d.tsqui contiendra tous les fichiers de déclaration manquants de divers packages:

Index.ts:

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

C'est ce qui a fonctionné de moi.

npm install --save readline

honkskillet
la source
0

J'ai tout essayé ici, mais pour moi, c'était un problème complètement différent: j'ai dû supprimer de mes *.d.tsdéclarations d'importation:

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

Après avoir supprimé l'erreur est parti ...

Clarification : lorsque nous déclarons un module dans un *.d.tsfichier, il est automatiquement récupéré par le compilateur Typescript en tant que module ambiant (celui que vous n'avez pas besoin d'importer explicitement). Une fois que nous avons spécifié le import ... from ..., le fichier devient maintenant un module normal (ES6), et ne sera donc pas récupéré automatiquement. Par conséquent, si vous souhaitez qu'il se comporte comme un module ambiant , utilisez un style d'importation différent comme ceci:

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

Vous pouvez simplement l'importer en utilisant require comme code suivant:

var _ = require('your_module_name');
Riyad Khalifeh
la source