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

我读了TypeScript模块分辨率的工作原理。

我有以下存储库:@陈志立。编译后的目录结构如下:

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

我做错了什么?

1130911 次浏览

对于您正在安装自己的npm包的情况

如果您使用的是第三方包,请参阅我的答案在下面

package.json中的"main": "dist/index.js"中删除.js

"main": "dist/index",

添加#0在#1每个TypeScript文档

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

文件夹dist是TS编译器存储模块文件的地方。

这里有两个解决方案

当一个模块不是你的-尝试从@types安装类型:

npm install -D @types/module-name

如果出现上述安装错误-请尝试将import语句更改为require

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

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

// foo.d.tsdeclare module 'foo';

然后当你导入foo时,它只会被键入为any


或者,如果你想滚动自己的打字,你也可以这样做:

// foo.d.tsdeclare 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将编译。

TypeScript基本上是实现规则并在代码中添加类型,以使其更清晰,更准确,因为JavaScript缺乏约束。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文件并在compilerOptions中添加"typeRoots": [ "../../typings", "../../node_modules/@types"](与您的文件夹的正确相对路径),让TypeScript知道它可以在哪里找到您的库和模块的类型定义,并向文件添加新属性"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规则。

我也得到了这个,让我困惑了一段时间,即使模块和类型已经安装并多次重新加载我的IDE。

在我的情况下,修复它的是终止终端进程、删除node_modules、清除节点包管理器缓存并执行新的install然后重新加载编辑器。

我在使用带有用打字稿编写的反应应用程序的节点模块时遇到了同样的问题。该模块使用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的文件旁边添加了一个my-module.d.ts文件,并使用建议的行。然后我得到了错误:

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

如果我在js应用程序中使用它,客户端实际上已经导出并正常工作。此外,前面的消息告诉我编译器正在查找正确的文件(/node_modules/my-module/lib/index.jsmy-module/package.json"main"元素中定义)。

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

    "noImplicitAny": false,

这种方式对我有效:

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}

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

// @ts-ignore

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

编辑:您还可以将"allowJs": true添加到您的tsconfig文件中。

不幸的是,我们无法控制包编写器是否打扰声明文件。我倾向于做的是有一个像index.d.ts这样的文件,它将包含来自各种包的所有缺失的声明文件:

Index.d.ts:

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

并在您的tsconfig.js中引用它:

"include": ["src/**/*.ts","src/**/*.tsx","src/**/*.vue","tests/**/*.ts","tests/**/*.tsx","index.d.ts" // this]

简单地说,您可以使用需要导入它,如下代码:

var _ = require('your_module_name');

一个简单的修复:

// example.d.tsdeclare module 'foo';

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

// example.d.tsdeclare module 'foo'{// exampleexport function getName(): string}

怎么用呢?很简单。

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

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

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

删除错误后消失了…

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

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

检查"tsconfig.json"文件中的编译选项"include""exclude"。如果它不存在,只需通过通知您的<强>根目录来添加它们。

// tsconfig.json{"compilerOptions": {..."include": ["src",],"exclude": ["node_modules",]}

我只是通过从"exclude"中删除扩展语句"*.spec.ts"来解决我的愚蠢问题,因为当在这些文件中包含"import"时,总会出现问题。

这就是我让它工作的方式。

在我的例子中,我使用了一个没有定义类型的库:react-mobile-datepicker

一种。在/src中创建一个文件夹。在我的情况下,我使用了此路径:/src/typings/

b。创建一个.d.ts文件。对于我的示例:/src/typings/react-mobile-datepicker.d.ts

c。我使用以下代码扩展其属性并使其类型安全:

declare module 'react-mobile-datepicker' {class DatePicker extends React.Component<DatePickerProps, any> {}
interface DatePickerProps {isPopup?: boolean;theme?: string;dateConfig?: DatePickerConfig;}
export interface DatePickerConfig {prop1: number;pro2: string;}export default DatePicker;}

d.导入您的类型,就像您通常使用第三方库时所做的那样。

import DatePicker, { DatePickerConfig, DatePickerConfigDate } from 'react-mobile-datepicker';

e.更改tsconfig.json并添加这段代码:

{"compilerOptions": {//...other properties"typeRoots": ["src/typings","node_modules/@types"]}}

链接到我用作来源的文章:

https://templecoding.com/blog/2016/03/31/creating-typescript-typings-for-existing-react-components

https://www.credera.com/insights/typescript-adding-custom-type-definitions-for-existing-libraries

如果您已经安装了模块并且仍然收到错误,一个简短而甜蜜的解决方案是通过在该行上方添加以下行来忽略错误消息

// @ts-ignore: Unreachable code error

如果导入不适合您

import * as html2pdf from 'html2pdf.js';

注释代码,将下面的脚本文件保存在官方文档中给出的index.html中。

<script src="https://rawgit.com/eKoopmans/html2pdf/master/dist/html2pdf.bundle.min.js"></script>

并在您正在使用的组件中声明html2pdf变量。

declare var html2pdf: any;

就是这样。我在这个问题上卡住了两天,但终于解决了。

解决方案:您所要做的就是编辑您的TypeScript Config文件tsconfig.json并添加一个新的键值对作为

"compilerOptions": {"noImplicitAny": false}

如果您在网络风暴中看到此错误,并且您刚刚安装了包,您可能需要重新启动打字稿服务才能将其拾取。

  • 打开帮助菜单
  • 找到一个行动
  • 搜索Restart Typescript Service

输入图片描述

输入图片描述

来自@ktretyak和@Retsam的答案是正确的,但我想添加一个完整的实时示例以及我必须做的事情:

错误:

错误TS7016(TS)找不到模块的声明文件'反应-区域-选择'。

'C:/Repo/node_modules/RegionSelect.js'隐式地有一个'any'类型。

如果存在,请尝试npm i --save-dev @types/react-region-select或添加新声明(.d.ts)包含“声明模块”的文件

运行npm i --save-dev @types/react-region-select给出错误:

npm ERR!代码E404

npm ERR!404未找到-GEThttps://registry.npmjs.org/@类型%2freact-的区域选择-未找到

npm错误!404'@类型/react-region-select@latest'不是在npm注册表中。

404您应该bug作者发布它(或自己使用名称!)

npm ERR!404注意你也可以从npm tarball、文件夹、超文本传输协议url或git url安装。

鉴于create-react-app创建了一个名为react-app-env.d.ts的文件,我试图将declare module 'react-region-select';放在那里,但我仍然收到错误。

然后我在src中创建了一个名为typings的新文件夹和一个名为react-region-select.d.ts的文件。在那里我像这样声明了模块:

declare module 'react-region-select';

这样做之后,错误消失了,我可以像留档状态一样导入它:

import RegionSelect from "react-region-select";

https://github.com/casavi/react-region-select

对我有用的是将依赖项安装为开发依赖项。上面禁用隐式类型检查的解决方案有效,但这让我无法利用严格类型的代码。所以你要做的就是在所有的@type模块安装中附加--save-dev标志。希望对你也有效

创建具有任意名称和.d.ts扩展名的文件。

ex:index.d.ts

tsconfig.json文件的include键下推送此文件名:

  "include": ["src","index.d.ts"]

您可能需要创建扩展名为.d.ts的文件。

tsconfig.json文件的include键下推送此文件名:

  "include": ["src","index.d.ts"]

应该是工作上的事

您所要做的就是编辑您的TypeScript配置文件(tsconfig.json)并添加一个新的键值对作为

是否必选

我在许多项目中的许多包都面临同样的问题。所以我创建了声明器,一个自动生成类型声明的npm包。

它基本上是通过在后台运行tsc --emitDeclarationOnly来工作的。

您可以从npm安装它:

npm install --save-dev declaratoryarn add -D declarator

然后创建一个简单的declarator.json文件:

{"$schema": "https://raw.githubusercontent.com/ArthurFiorette/declarator/master/schema.json","packages": ["package1","package2"]}

并创建一个脚本来运行它:

使用postinstall脚本将在每个包安装上运行它,可能很有用

{"scripts": {"postinstall": "declarator"}}

它不会生成强大的类型,并且您可能会在此过程中遇到许多any类型,但有比没有好得多

阅读更多:https://github.com/ArthurFiorette/declarator#readme

import { io, Socket,SocketIOClient } from 'socket.io-client';

在component.ts之上添加这个在我的案例中起作用。

只需在项目的根目录中创建一个名为typings.d.ts的文件。在此文件中只需添加declare module <module_name>。在这里,module_name可以是您要导入的任何模块名称。最后,打开tsconfig.json文件并将文件typings.d.ts包含在名为include array的数组中。

// typings.d.tsdeclare module 'abc-module';
// tsconfig.json{..."include": ["src", "typings.d.ts"]}
// BOOM, Problem solved!!!

此技术为您的模块提供了一个名为“any”的类型。更多信息:https://medium.com/@steveruiz/using-a-javascript库没有类型声明项目3643490015f3

从TypeScript留档:

请注意,“打字”字段与“类型”同义,也可以使用。

另请注意,如果您的主声明文件名为index.d.ts并且位于包的根目录(index.js旁边)您不需要标记类型属性,尽管建议这样做。

出于某种原因,我的“类型”属性指向一些main.d.ts.从package.json中删除该行,它开始工作。

基于瑞森的回答,您还可以在yourDeclarations.d.ts文件中使用通配符(*)。例如,如果您尝试导入文件,例如.css.webp文件,您可以在文件类型声明的开头放置*。它看起来像这样⤵

declare module '*.webp';

现在,您可以导入您想要的所有.webp文件,而不会出现任何错误。

对于在React中遇到此错误的人,在tsconfig.json中,set

"compilerOptions" : {..."strict": false,...}

来自React的create-react-app的自动生成配置将该标志设置为true

这对我有用。

// modules.d.tsdeclare module 'my-module';
// tsconfig.json{..."include": [..."src", "modules.d.ts"]}
// Importimport * as MyModule from 'my-module'...const theModule = MyModule()...

我在角度项目中的uuid模块遇到了同样的问题。

当然不是为了prod,但是把“//@ts-的忽略”放在前面一行很快就“解决”了我的问题。

输入图片描述

在大多数情况下,你可能会为你的依赖项安装一个类型包,无论哪种方式,你都可以在你的tsconfig.json文件中添加lowJs->true

在我的情况下,解决此问题的3种不同方法都不起作用。一旦您在package.json中将“type”设置为“模块”,那么它将符合ES模块而不是Common JS语法。我可以根据我的package.json设置使用ES模块语法来解决这个问题。

import ws from 'ws'
export const create = (/** @type {string} */ accessToken) => {const WebSocket = ws;return new WebSocket(endpoint, accessToken, sslOptions);}

通过这种方式,您可以在ws模块中使用WebSocket类。它是节点模块的一个示例,但您基本上可以在其中放置任何类型的节点模块和函数。

下面是不是为我工作:

  1. npm install -D @types/module-name
  2. const foo = require('module-name');
// index.d.tsdeclare module 'foo';
  1. tsconfig.json配置
"noImplicitAny": true,"allowJs": true