找不到模块“模块名称”的声明文件。'/path/to/module-name.js'隐式具有'any'类型


303

我阅读了TypeScript 模块解析的工作原理。

我有以下存储库:@ ts-stack / di。编译后的目录结构如下:

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

我在package.json中写道"main": "dist/index.js"

在Node.js中,一切正常,但是TypeScript:

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

找不到模块'@ ts-stack / di'的声明文件。'/path/to/node_modules/@ts-stack/di/dist/index.js'隐式具有'any'类型。

但是,如果我按以下方式导入,则一切正常:

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

我究竟做错了什么?

Answers:


295

这是另外两个解决方案

如果不是您自己的模块,请尝试从@types以下位置安装类型:

npm install -D @types/module-name

如果以上安装错误-尝试将import语句更改为require

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

13
如果找不到名称,请为TypeScript 2.0运行此命令:npm install @types/node --save-dev
Ogglas

120
如果模块没有@types包怎么办?
Daniel Kmak

37
我认为使用require代替import有点反模式:最好在.d.ts文件中声明模块;请参阅下面的答案。
Retsam

2
用法示例: const mdbreact = require('mdbreact'); const { Button, Card, CardBody, CardText, CardTitle, CardImage } = mdbreact;
Sgedda

1
这是不好的建议。这完全否定了TypeScript的观点,并否定了一般的FOSS态度,即“足够容易的事情值得贡献”。如果缺少键入a,则表明有人搜索了它,但没有发布您的键入或提交PR,或者如果您只是想绕开它,则不要使用键入系统。
戴夫·麦金托什

265

如果您要导入的第三方模块'foo'在库本身或@types/foo程序包(从DefinitelyTyped存储库生成)中不提供任何类型,则可以通过在模块中声明该模块来消除此错误。带有.d.ts扩展名的文件。TypeScript .d.ts在与普通.ts文件相同的位置查找文件:在中的“文件”,“包含”和“排除”下指定tsconfig.json

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

然后,在您导入时foo,将其键入为any


另外,如果您想滚动自己的类型,也可以这样做:

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

然后,它将正确编译:

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

您不必为模块提供完整的类型,只需为您实际使用的位提供足够的(并希望为其进行适当的类型化),因此,如果您使用的API数量很少,则这样做特别容易。


另一方面,如果您不关心外部库的类型,并且希望将所有没有类型的库导入为any,则可以将其添加到具有.d.ts扩展名的文件中:

declare module '*';

这样做的好处(和缺点)是,您可以导入任何东西,TS可以编译。


27
编译器在哪里寻找d.ts文件?您应该提供任何配置typeRoots吗?
汤姆(Tom)

17
@Tom .d.ts在与普通.ts文件相同的位置查找文件:在中指定了“ files”,“ include”和“ exclude” tsconfig.json。我不建议typeRoots为此目的使用:它用于放置外部类型模块(即node_modules/@types),而不是单个.d.ts文件。
Retsam '18年

3
我收到“文件foo.d.ts不是模块”的消息
Nathan H,

2
看来该通配符文件需要称为“ typings.d.ts”
jacob

4
我应该把这个.d.ts文件放在哪里?
tonix

126

如果您需要快速修复,只需在导入行之前添加以下内容:

// @ts-ignore

7
谢谢,对我的情况最有用的答案。
大卫

这会在eslint的更高版本中导致错误:error Do not use "// @ts-ignore" comments because they suppress compilation errors @typescript-eslint/ban-ts-ignore
Hykilpikonna

91

那种感觉,当你正在寻找了两天,发现它是这样的:只是删除.js"main": "dist/index.js"package.json,一切工作正常!

"main": "dist/index",

UPD:如果您有自己的npm软件包,则此答案是相对的;如果没有,请参阅下面的我的答案

如果以上回答没有解决您的进口模块,尝试只需添加typingspackage.json

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

当然,这里是文件夹dist-它是存储模块文件的位置。


在过去的几天里,我多次遇到您的问题和您的答案,我想补充一点,我所缺少的是在.d.ts文件中声明这些类型,因此,就我而言,安装的节点模块没有类型(我无法明确地安装它们的类型)开始通过在文件中声明他们合作写“申报模块‘MYDesiredModule’
胡安

谢谢。在我的package.json中添加“ typings”:“ dist / index”对我有用。奇怪的是,当我什

感谢您的见解!如果我尝试使用VS Code定义,为什么我自己的npm包不起作用?我在这里创建了一个问题,到目前为止还没有运气... stackoverflow.com/questions/59128917/…–
tonix

您需要在dist文件夹中添加文件“ index.d.ts”并declare module "moduleName" 同时放置
Sunny Sun

42

由于Javascript缺乏约束,TypeScript基本上是在实现规则并向代码中添加类型,以使其更清晰,更准确。TypeScript要求您描述数据,以便编译器可以检查您的代码并查找错误。如果您使用的是不匹配的类型,超出范围或尝试返回其他类型,则编译器会通知您。因此,当您使用带有TypeScript的外部库和模块时,它们需要包含描述该代码中的类型的文件。这些文件称为带有扩展名的类型声明文件d.ts。npm模块的大多数声明类型已经编写,您可以使用npm install @types/module_name(其中module_name是要包含其类型的模块的名称)将它们包括在内。

但是,有些模块没有类型定义,为了使错误消失并使用导入模块import * as module_name from 'module-name',请typings在项目的根目录中创建一个文件夹,在内部使用模块名创建一个新文件夹,并在其中文件夹中创建一个module_name.d.ts文件并写入declare module 'module_name'。在此之后就到你的tsconfig.json文件,并添加"typeRoots": [ "../../typings", "../../node_modules/@types"]compilerOptions(用正确的相对路径到您的文件夹),让打字稿知道在哪里可以找到你的库和模块的类型定义和新的属性添加"exclude": ["../../node_modules", "../../typings"]到文件中。这是tsconfig.json文件的外观示例:

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

这样,错误将消失,您将能够坚持使用最新的ES6和TypeScript规则。


只有命名输入文件才对我有用index.d.ts。除此之外,这是唯一对我有效的解决方案。
克里斯·海恩斯

21

对于其他阅读本文的人,请尝试将.js文件重命名为.ts

编辑:您也可以添加"allowJs": true到tsconfig文件。


是的,“ react-fusioncharts”也有同样的问题,这种解决方案就像一个魅力。
yawningphantom

16

这种方式对我有用:

1.在声明文件中添加自己的声明,例如index.d.ts(可能在项目根目录下)
declare module 'Injector';
2.将您的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
    }

-编辑:模块名称周围需要用引号引起来


4

将节点模块与以打字稿编写的react应用程序一起使用时,我遇到了同样的问题。使用已成功安装该模块npm i --save my-module。它用javascript编写并导出一个Client类。

带有:

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

编译失败,并显示以下错误:

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-module不存在,因此我my-module.d.tsmy-module导入文件的旁边添加了一个文件,并带有建议的行。然后我得到了错误:

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

如果我在js应用程序中使用客户端,则该客户端实际上已导出并且可以正常工作。同样,上一条消息告诉我,编译器正在寻找正确的文件(/node_modules/my-module/lib/index.jsmy-module/package.json "main"element中定义)。

我通过告诉编译器我不关心隐式的问题解决了这个问题any,也就是说,我将文件设置为false以下行tsconfig.json

    "noImplicitAny": false,

14
我的意思是,这可行,但是您将失去严格键入其余代码的能力。这不是一个很好的解决方法。
phillyslick,

3

修复您的问题很简单:

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

如果要声明对象的接口(推荐用于大型项目),则可以使用:

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

如何使用?简单..

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

2

即使已经安装了模块和类型并多次重新加载IDE,我也感到困惑。

在我看来,解决此问题的方法是终止终端进程,删除node_modules,清除节点程序包管理器缓存并install重新进行刷新,然后重新加载编辑器。


2

不幸的是,程序包编写者是否会为声明文件而烦恼。我倾向于做的是拥有一个文件,index.d.ts其中将包含各种程序包中所有缺少的声明文件:

Index.ts:

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


0

我已经在这里进行了所有尝试,但是对我来说,这是一个完全不同的问题:我必须从*.d.ts所有导入语句中删除:

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

清除错误后,错误消失了...

澄清:当我们在*.d.ts文件中声明一个模块时,Typescript编译器会自动将其拾取为环境模块(不需要显式导入的模块)。一旦指定import ... from ...,该文件即成为普通(ES6)模块,因此将不会自动获取。因此,如果您仍然希望它充当环境模块,请使用其他导入样式,如下所示:

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.