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

ktr*_*yak 199 node-modules typescript

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

我有以下存储库:ts-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
Run Code Online (Sandbox Code Playgroud)

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

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

import {Injector} from 'ts-di';
Run Code Online (Sandbox Code Playgroud)

无法找到模块'ts-di'的声明文件.'/path/to/node_modules/ts-di/dist/index.js'隐式具有'任意'类型.

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

import {Injector} from '/path/to/node_modules/ts-di/dist/index.js';
Run Code Online (Sandbox Code Playgroud)

我究竟做错了什么?

ktr*_*yak 224

另外两种方式,当一个模块不是你的 - 只需尝试安装它来自@types:

npm install -D @types/module-name
Run Code Online (Sandbox Code Playgroud)

或者,如果安装错误 - 尝试重写importrequire:

// import * as yourModuleName from 'module-name';
const yourModuleName = require('module-name');
Run Code Online (Sandbox Code Playgroud)

  • 如果模块没有@types包怎么办? (91认同)
  • 我认为使用`require`而不是`import`有点反模式:最好在`.d.ts`文件中声明模块; 请参阅下面的答案. (23认同)
  • 如果找不到名称,请为TypeScript 2.0运行此命令:`npm install @ types/node --save-dev` (12认同)
  • 谢谢,它对我有用!为什么会发生这种情况呢? (6认同)
  • 用法示例:`const mdbreact = require('mdbreact'); const {Button,Card,CardBody,CardText,CardTitle,CardImage} = mdbreact;` (2认同)
  • 我正在使用带有 YARN 的 React TypeScript 项目,只需要工作。谢谢 ```const yourModuleName = require('模块名称');``` (2认同)
  • 如果模块是你的怎么办?如何处理该模块才能使其在发布后不再出现此问题? (2认同)

Ret*_*sam 161

如果您要导入的第三方模块'foo'没有提供任何类型,无论是在库本身,还是在@types/foo包中(从DefinitelyTyped存储库生成),那么您可以通过在模块中声明模块来消除此错误.d.ts文件:

// foo.d.ts
declare module 'foo';
Run Code Online (Sandbox Code Playgroud)

然后当你导入foo它时,只需键入即可any.


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

// foo.d.ts
declare module 'foo' {
    export function getRandomNumber(): number
} 
Run Code Online (Sandbox Code Playgroud)

然后这将正确编译:

import { getRandomNumber } from 'foo';
const x = getRandomNumber(); // x is inferred as number
Run Code Online (Sandbox Code Playgroud)

您不必为模块提供完整的输入,只需足够用于您实际使用的位(并且需要正确的输入),因此如果您使用相当少量的API,则特别容易.


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

declare module '*';
Run Code Online (Sandbox Code Playgroud)

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

  • 编译器在哪里查找`d.ts`文件?你应该提供任何配置,如`typeRoots`? (16认同)
  • @Tom它在相同的地方查找`.d.ts`文件,它们将查找正常的`.ts`文件:在`tsconfig.json`中指定"files","include"和"exclude".我不建议为此目的使用`typeRoots`:它用于外部类型模块的位置(即`node_modules/@ types`),而不是单独的`.d.ts`文件. (10认同)
  • 如果您在使用“ts-node”时遇到此类错误,请查看 ts-node 文档 [帮助!我的类型丢失了!](https://github.com/TypeStrong/ts-node#help-my-types-are-missing)。我花了几个小时试图找出为什么编译器看不到我的“.d.ts”。 (5认同)
  • 为了使其工作,我必须将“declare module '...”作为“module.d.ts”文件中的第一行代码,并将所有导入包含在模块块内(而不是之前)。在我这样做之前,编译器说它找不到该模块。 (4认同)
  • 我得到“文件foo.d.ts不是模块” (3认同)

ktr*_*yak 79

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

"main": "dist/index",
Run Code Online (Sandbox Code Playgroud)

UPD:这个答案是相对的,如果你有自己的npm包,如果没有 - 请参阅下面的答案.

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

"main": "dist/index",
"typings": "dist/index",
Run Code Online (Sandbox Code Playgroud)

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

  • 我在这个问题上遇到了一些困难:当您拥有自己的包时,请务必删除包的“dist”文件夹(或项目中的整个“node_modules”)的旧内容,然后再次运行打包程序。即使在这次编辑之后,我在“dist”中仍然有旧的“index.js”,这给我带来了警告。 (3认同)
  • 谢谢你 - 你的英语不是很清楚,但这有帮助,我的“打字”不正确。我做了一些更改以使答案更清晰。 (3认同)

Lir*_*n H 59

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

// @ts-ignore
Run Code Online (Sandbox Code Playgroud)

  • 当您想睡觉并部署它时,这是一个解决方案。 (17认同)
  • 这不是解决办法或答案,而是抑制投诉的一种方法。 (10认同)
  • @Hykilpikonna我相信你可以在使用 `// @ts-ignore` 之前添加 /`* eslint-disable */` 来禁用 eslint,然后在问题代码行之后添加 `/* eslint-enable */` 来重新- 为文件的其余部分启用 eslint。 (7认同)
  • 您还可以在 ts 行之前添加 `// eslint-disable-next-line @typescript-eslint/ban-ts-comment` (4认同)
  • 这会在更高版本的 eslint 中导致错误: `error 不要使用 "// @ts-ignore" 注释,因为它们会抑制编译错误 @typescript-eslint/ban-ts-ignore` (2认同)

Mar*_*ett 38

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

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

  • 我已将“allowJs”设置为“true”,但它不起作用 (14认同)

Mar*_*ski 29

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文件,并添加"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"
    ]
}
Run Code Online (Sandbox Code Playgroud)

通过这样做,错误将消失,您将能够坚持最新的ES6和TypeScript规则.


小智 25

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!!!
Run Code Online (Sandbox Code Playgroud)

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


Bin*_* Ho 20

这对我有用。

// modules.d.ts 
declare module 'my-module';
Run Code Online (Sandbox Code Playgroud)
// tsconfig.json 
{
  ...
  "include": [
    ...
    "src", "modules.d.ts"
  ]
}

Run Code Online (Sandbox Code Playgroud)
// Import
import * as MyModule from 'my-module'
...
const theModule = MyModule()
...
Run Code Online (Sandbox Code Playgroud)


San*_*tos 15

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

就我而言,我使用了一个没有定义类型的库:react-mobile-datepicker

A。里面创建一个文件夹/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;
}
Run Code Online (Sandbox Code Playgroud)

d. 像使用第 3 方库时通常执行的操作一样导入您的类型。

import DatePicker, { DatePickerConfig, DatePickerConfigDate } from 'react-mobile-datepicker';
Run Code Online (Sandbox Code Playgroud)

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

{
  "compilerOptions": {
    //...other properties
    "typeRoots": [
      "src/typings",
      "node_modules/@types"
    ]
  }}
Run Code Online (Sandbox Code Playgroud)

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

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


Luk*_*gan 8

不幸的是,我们无法控制包编写者是否会为声明文件烦恼。我倾向于做的是有一个文件,index.d.ts其中将包含来自各种包的所有丢失的声明文件:

索引.d.ts:

declare module 'v-tooltip';
declare module 'parse5';
declare module 'emoji-mart-vue-fast';
Run Code Online (Sandbox Code Playgroud)

并在您的tsconfig.js

"include": [
    "src/**/*.ts",
    "src/**/*.tsx",
    "src/**/*.vue",
    "tests/**/*.ts",
    "tests/**/*.tsx",
    "index.d.ts" // this
  ]
Run Code Online (Sandbox Code Playgroud)


小智 6

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

和:

import * as MyModule from 'my-module';
let client: MyModule.Client = new MyModule.Client();
Run Code Online (Sandbox Code Playgroud)

编译失败并显示错误:

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';`
Run Code Online (Sandbox Code Playgroud)

@types/my-module不存在,所以我my-module.d.tsmy-module导入的文件旁边添加了一个文件,并带有建议的行。然后我得到了错误:

Namespace '"my-module"' has no exported member 'Client'.
Run Code Online (Sandbox Code Playgroud)

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

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

    "noImplicitAny": false,
Run Code Online (Sandbox Code Playgroud)

  • 我的意思是,这行得通,但您失去了严格键入其余代码的能力。这不是一个很好的解决方法。 (21认同)

Abd*_*yir 6

一个简单的修复:

// example.d.ts
declare module 'foo';
Run Code Online (Sandbox Code Playgroud)

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

// example.d.ts
declare module 'foo'{
    // example
    export function getName(): string
}
Run Code Online (Sandbox Code Playgroud)

如何使用它?简单的..

const x = require('foo') // or import x from 'foo'
x.getName() // intellisense can read this
Run Code Online (Sandbox Code Playgroud)


小智 6

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

// tsconfig.json
{
  "compilerOptions": {
  ...
  "include": [
    "src", 
  ],
  "exclude": [
    "node_modules", 
  ]
}
Run Code Online (Sandbox Code Playgroud)

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


Aba*_*any 6

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

"compilerOptions": {
"noImplicitAny": false
}
Run Code Online (Sandbox Code Playgroud)

  • 如果您发现自己将其关闭,您不妨在 javascript 中运行。这个答案中的其他选项是更好的选择。当然,任何类型都可以让您变形对象并将圆钉塞进方孔,但您失去了关于期望输入的知识。您可以添加类型保护,但是没有任何在转译时完成的操作,类型保护是在运行时完成的。 (4认同)
  • 这不会只是删除错误消息而不是解决问题吗? (2认同)

小智 6

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


Lum*_*ete 5

这种方式对我有用:

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

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


小智 5

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

// @ts-ignore: Unreachable code error
Run Code Online (Sandbox Code Playgroud)


Ogg*_*las 5

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

错误:

错误 TS7016 (TS) 找不到模块“react-region-select”的声明文件。

'C:/Repo/node_modules/react-region-select/lib/RegionSelect.js' 隐式具有 'any' 类型。

尝试npm i --save-dev @types/react-region-select它是否存在或添加包含“declare module”的新声明(.d.ts)文件

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

npm 错误!代码 E404

npm 错误!404 未找到 - GET https://registry.npmjs.org/@types%2freact-region-select - 未找到

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

npm 错误!第404章 你应该骚扰作者发布它(或者自己使用这个名字!)

npm 错误!404 请注意,您还可以从 npm tarball、文件夹、http 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';
Run Code Online (Sandbox Code Playgroud)

这样做之后,错误消失了,我可以像文档所述那样导入它:

import RegionSelect from "react-region-select"; 
Run Code Online (Sandbox Code Playgroud)

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


小智 5

就我而言,解决此问题的 3 种不同方法均无效。一旦你在 package.json 中将“type”设置为“module”,那么它将遵循 ES Module 而不是 CommonJS 语法。我能够根据我的 package.json 设置使用 ES 模块语法来解决这个问题。

import ws from 'ws'

export const create = (/** @type {string} */ accessToken) => {
    const WebSocket = ws;
    return new WebSocket(endpoint, accessToken, sslOptions);
}
Run Code Online (Sandbox Code Playgroud)

这样您就可以在“ws”模块中使用 WebSocket 类。这是节点模块的示例,但基本上您可以在其中放置任何类型的节点模块和函数。

下面这些对我不起作用:

  1. npm install -D @types/module-name
  2. const foo = require('module-name');
// index.d.ts
declare module 'foo';
Run Code Online (Sandbox Code Playgroud)
  1. 来自 tsconfig.json 的配置
"noImplicitAny": true,
"allowJs": true
Run Code Online (Sandbox Code Playgroud)