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

Could not find a declaration file for module 'module-name'. '/path/to/module-name.js' implicitly has an 'any' type

我阅读了 TypeScript module resolution 的工作原理。

我有以下存储库:@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';

Could not find a declaration file for module '@ts-stack/di'. '/path/to/node_modules/@ts-stack/di/dist/index.js' implicitly has an 'any' type.

然而,如果我按如下方式导入,那么一切正常:

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

我做错了什么?

针对安装自己的npm包的情况

如果您使用的是第三方包,请参阅

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

"main": "dist/index",

同时添加typings in package.json per the TypeScript docs:

"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 包(从 DefinitelyTyped 存储库),那么您可以通过在具有 .d.ts 扩展名的文件中声明该模块来消除此错误。 TypeScript 在与查找普通 .ts 文件相同的位置查找 .d.ts 文件:如 "files"、"include" 和 "exclude" 中指定的 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,您可以将其添加到带有 [=16] 的文件中=] 扩展名:

declare module '*';

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

TypeScript 基本上是在执行规则并向您的代码添加类型,以使其更清晰、更准确,因为 Javascript 中缺少约束。 TypeScript 要求您描述您的数据,以便编译器可以检查您的代码并发现错误。如果您正在使用不匹配的类型、超出您的范围或您尝试 return 不同的类型,编译器会通知您。 因此,当您将外部库和模块与 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 然后重新加载编辑器。

我在使用节点模块和用打字稿编写的 React 应用程序时遇到了同样的问题。该模块已使用 npm i --save my-module 成功安装。 写成javascript,导出一个Client class.

有:

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
  ]

只需使用 require 导入它,如下代码:

var _ = require('your_module_name');

一个简单的修复:

// 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

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

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

删除错误后消失了...

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

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

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

// 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.像往常一样在使用第 3 方库时导入您的类型。

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;

就是这样。在这个问题上卡了2天,终于解决了。

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

"compilerOptions": {
"noImplicitAny": false
}

如果您在 Webstorm 中看到此错误,并且您刚刚安装了该软件包,您可能需要先重新启动 typescript 服务它会捡起它。

  • 打开帮助菜单
  • 查找操作
  • 搜索 Restart Typescript Service

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

错误:

Error TS7016 (TS) Could not find a declaration file for module 'react-region-select'.

'C:/Repo/node_modules/react-region-select/lib/RegionSelect.js' implicitly has an 'any' type.

Try npm i --save-dev @types/react-region-select if it exists or add a new declaration (.d.ts) file containing `declare module

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

npm ERR! code E404

npm ERR! 404 Not Found - GET https://registry.npmjs.org/@types%2freact-region-select - Not found

npm ERR! 404 '@types/react-region-select@latest' is not in the npm registry.

npm ERR! 404 You should bug the author to publish it (or use the name yourself!)

npm ERR! 404 Note that you can also install from a npm tarball, folder, http url, or 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

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

使用任意名称和 .d.ts 扩展名创建文件。

例如:index.d.ts

将此文件名压入 tsconfig.json 文件的 include 键下:

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

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

将此文件名压入 tsconfig.json 文件的 include 键下:

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

它应该工作

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

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

它基本上由 运行ning tsc --emitDeclarationOnly 在后台工作。

你可以从 npm 安装它:

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

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

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

并为 运行 创建一个脚本:

使用安装后脚本 运行 它会在每个软件包安装时出现,可能会有用

{
  "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.ts 
declare module 'abc-module';

// tsconfig.json 
{
  ...
"include": [
    "src", "typings.d.ts"
  ]
}

// BOOM, Problem solved!!!

此技术为您的模块提供了一个名为“any”的类型。 更多信息:https://medium.com/@steveruiz/using-a-javascript-library-without-type-declarations-in-a-typescript-project-3643490015f3

来自 Typescript 文档:

Note that the "typings" field is synonymous with "types", and could be used as well.

Also note that if your main declaration file is named index.d.ts and lives at the root of the package (next to index.js) you do not need to mark the types property, though it is advisable to do so.

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

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

declare module '*.webp';

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

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

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

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

这对我有用。

// modules.d.ts 
declare module 'my-module';
// tsconfig.json 
{
  ...
  "include": [
    ...
    "src", "modules.d.ts"
  ]
}

// Import
import * as MyModule from 'my-module'
...
const theModule = MyModule()
...

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

在上一行加上'// @ts-ignore'解决了我的问题