【问题标题】:Could not find a declaration file for module 'module-name'. '/path/to/module-name.js' implicitly has an 'any' type找不到模块“模块名称”的声明文件。 '/path/to/module-name.js' 隐含一个 'any' 类型
【发布时间】:2017-05-08 15:14:19
【问题描述】:

我阅读了 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';

找不到模块“@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';

我做错了什么?

【问题讨论】:

标签: typescript node-modules


【解决方案1】:

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

如果您使用的是第三方软件包,请参阅my answer below

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

"main": "dist/index",

另外加typings in package.json per the TypeScript docs:

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

dist 文件夹是 TS 编译器存储模块文件的位置。

【讨论】:

  • 我有点挣扎:当你有自己的包时,一定要删除你的包的 dist 文件夹的旧内容(或你项目中的整个 node_modules)并运行你的再次捆绑器。即使在此编辑之后,我仍然在 dist 中有旧的 index.js,这对我造成了警告。
  • 谢谢你 - 你的英语不是很清楚,但这有帮助,我的 typings 不正确。我做了一些更改以使答案更清晰。
  • @optimista 我也遇到了陈旧的 dist 问题。 rm -rf ./dist/* ; tsc
【解决方案2】:

来自 Typescript 文档:

请注意,"typings" 字段与 "types" 同义,也可以使用。

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

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

【讨论】:

    【解决方案3】:
    Just create a file named "typings.d.ts" in the root directory of your project. 
    Inside this file just add "declare module "<module_name>". Here, module_name can be any module's name that you want to import. Finally, open the tsconfig.json file and include the file "typings.d.ts" inside the array named as "include array".
    
    // typings.d.ts 
    declare module 'abc-module';
    
    // tsconfig.json 
    {
      ...
    "include": [
        "src", "typings.d.ts"
      ]
    }
    
    // BOOM, Problem solved!!!
    
    This technique provides your module with a type named "any".
    For more info: https://medium.com/@steveruiz/using-a-javascript-library-without-type-declarations-in-a-typescript-project-3643490015f3
    

    【讨论】:

      【解决方案4】:
      import { io, Socket,SocketIOClient } from 'socket.io-client';
      

      在我的情况下,在 component.ts 之上添加它。

      【讨论】:

        【解决方案5】:

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

        它基本上是通过在后台运行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"]
        }
        

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

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

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

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

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

        【讨论】:

          【解决方案6】:

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

          【讨论】:

          • 这将抵消使用 Typescript 的好处。您基本上是在消除警告而不是修复它
          【解决方案7】:

          您是否需要创建带有.d.ts 扩展名的文件。

          将这个文件名推到tsconfig.json文件的include键下:

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

          应该可以了

          【讨论】:

            【解决方案8】:

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

            例如:index.d.ts

            将这个文件名推到tsconfig.json文件的include键下:

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

            【讨论】:

              【解决方案9】:

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

              【讨论】:

                【解决方案10】:

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

                错误:

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

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

                尝试npm i --save-dev @types/react-region-select(如果存在)或添加新声明 (.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';
                

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

                import RegionSelect from "react-region-select"; 
                

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

                【讨论】:

                  【解决方案11】:

                  不幸的是,包编写者是否需要声明文件,这不在我们的掌控之中。我倾向于做的是有一个像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
                    ]
                  

                  【讨论】:

                    【解决方案12】:

                    一个简单的修复:

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

                    【讨论】:

                      【解决方案13】:

                      如果您在 Webstorm 中看到此错误,并且您刚刚安装了该软件包,您可能需要重新启动 typescript 服务,然后它才能获取它。 p>

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

                      【讨论】:

                        【解决方案14】:

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

                        "compilerOptions": {
                        "noImplicitAny": false
                        }
                        

                        【讨论】:

                        • 这不只是删除错误消息而不是解决问题吗?
                        • 这将对您的 typescript 类型检查产生更广泛的影响,而不仅仅是让这个导入工作。请谨慎操作并阅读此设置,以确保您需要所有副作用。
                        【解决方案15】:

                        如果导入不适合您

                        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天,但终于解决了。

                        【讨论】:

                          【解决方案16】:

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

                          // @ts-ignore: Unreachable code error
                          

                          【讨论】:

                            【解决方案17】:

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

                            在我的例子中,我使用了一个没有定义类型的库: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。像往常一样在使用 3rd 方库的地方导入类型。

                            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

                            【讨论】:

                              【解决方案18】:

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

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

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

                              【讨论】:

                                【解决方案19】:

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

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

                                删除后错误消失了...

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

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

                                【讨论】:

                                • 这是一个动态导入并返回一个承诺......它只能在异步上下文中工作。好消息是知道。
                                【解决方案20】:

                                如果您要在库本身或 @types/foo 包(从 DefinitelyTyped 存储库生成)中导入不提供任何类型的第三方模块 'foo',那么您可以通过在具有.d.ts 扩展名的文件中声明模块来消除此错误。 TypeScript 在与普通.ts 文件相同的位置查找.d.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 会编译。

                                【讨论】:

                                • 编译器在哪里寻找d.ts 文件?您是否应该提供任何配置,例如typeRoots
                                • @Tom 它在与普通.ts 文件相同的位置查找.d.ts 文件:如@987654341 中指定的“文件”、“包含”和“排除” @。我不建议为此目的使用typeRoots:这是用于外部类型模块(即node_modules/@types)的位置,而不是单独的.d.ts 文件。
                                • 为了让它工作,我必须在module.d.ts文件中的第一行代码中设置declare module '...',并在模块块中包含任何导入,而不是在它之前。在我这样做之前,编译器说它找不到模块。
                                • declare module '*' 会确保只编译没有类型的包,还是会干扰有类型的包?
                                • 如果您在使用 ts-node 时遇到此类错误,请查看 ts-node 文档 Help! My Types Are Missing!。我花了几个小时试图找出为什么编译器看不到我的.d.ts
                                【解决方案21】:

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

                                // @ts-ignore
                                

                                【讨论】:

                                • 这会导致以后版本的eslint报错:error Do not use "// @ts-ignore" comments because they suppress compilation errors @typescript-eslint/ban-ts-ignore
                                • @Hykilpikonna 我相信您可以在使用 // @ts-ignore 之前添加 /* eslint-disable */ 以禁用 eslint,然后在问题代码行之后添加 /* eslint-enable */ 以重新启用其余的 eslint文件。
                                • 也可以在ts行前加// eslint-disable-next-line @typescript-eslint/ban-ts-comment
                                • 这不是修复或答案,而是压制投诉的一种方式。
                                【解决方案22】:

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

                                var _ = require('your_module_name');
                                

                                【讨论】:

                                  【解决方案23】:

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

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

                                  【讨论】:

                                  • 我已将allowJs 设置为true,但它不起作用
                                  【解决方案24】:

                                  这种方式适合我:

                                  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
                                      }
                                  

                                  -- 编辑:模块名称需要引号

                                  【讨论】:

                                    【解决方案25】:

                                    这里有另外两个解决方案

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

                                    npm install -D @types/module-name
                                    

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

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

                                    【讨论】:

                                    • 如果找不到名称,则需要为 TypeScript 2.0 运行此命令:npm install @types/node --save-dev
                                    • 如果模块没有@types包怎么办?
                                    • @DanielKmak,它是打字稿定义库。
                                    • 用法示例:const mdbreact = require('mdbreact'); const { Button, Card, CardBody, CardText, CardTitle, CardImage } = mdbreact;
                                    • 我正在使用带有 YARN 的 react typescript 项目,只需要工作。谢谢const yourModuleName = require('module-name');
                                    【解决方案26】:

                                    我在使用带有用 typescript 编写的 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 的文件旁边添加了一个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,
                                    

                                    【讨论】:

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

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

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

                                    【讨论】:

                                      【解决方案28】:

                                      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 规则。

                                      【讨论】:

                                      • 只有当我将打字文件命名为index.d.ts时它才对我有用。除此之外,这是唯一对我有用的解决方案。
                                      • 也为我工作(不需要将名称更改为index.d.ts)。对于那些使用ng new app-name 的默认应用程序结构的人,您可能需要您的路径具有一层,例如:"../node_modules""../typings" 等。另外,请确保module-name 部分在@ 987654338@ 语句与您在原始文件中导入它的方式完全相同。例如:在我的情况下,它必须是:declare module 'videojs-record/dist/videojs.record.js',因为这就是我在原始文件中导入它的方式。
                                      猜你喜欢
                                      • 2022-06-20
                                      • 2017-05-18
                                      • 1970-01-01
                                      • 1970-01-01
                                      • 2021-12-20
                                      • 2020-03-30
                                      • 2021-11-06
                                      • 1970-01-01
                                      相关资源
                                      最近更新 更多