首页 文章

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

提问于
浏览
84

我读了TypeScript module resolution的工作原理 .

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

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

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

import {Injector} from 'ts-di';

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

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

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

我究竟做错了什么?

6 回答

  • 57

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

    npm install -D @types/module-name
    

    或者,如果安装错误 - 尝试将 import 重写为 require

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

    当你想要两天并且发现它是这样的感觉:只需从 package.json 中删除 .js ,一切正常!

    "main": "dist/index",
    

    UPD :如果您有自己的npm包,这个答案是相对的,如果没有 - 请参阅my answer below .

    如果以上答案未解决导入您的模块,请尝试在 package.json 中添加 typings

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

    当然,这里的文件夹 dist - 它是's where stores your module'的文件 .

  • 9

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

    // 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会编译 .

  • 0

    TypeScript基本上是实现规则并向代码添加类型,以使其更加清晰和准确,因为Javascript中缺少约束 . TypeScript要求您描述数据,以便编译器可以检查您的代码并查找错误 . 如果您使用不匹配的类型,如果您超出范围或尝试返回其他类型,编译器将通知您 . 因此,当您使用带有TypeScript的外部库和模块时,它们需要包含描述该代码中类型的文件 . 这些文件名为 type declaration files ,扩展名为 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规则 .

  • -1

    我这样解决了这个问题:

    import * as foo from "foo";
    

    在我的情况下,当我尝试使用库导出的默认类时,会出现此问题 .

  • 48

    我有同样的问题,我通过这样更新 tsconfig.jsoncompilerOptions 来解决它:

    {
      "compilerOptions": {
        ...
        "noImplicitAny": false,
        ...
      },
      "exclude": [
        ...
      ]
    }
    

相关问题