即使 tsc 成功解决它,也找不到 Typescript 模块

Posted

技术标签:

【中文标题】即使 tsc 成功解决它,也找不到 Typescript 模块【英文标题】:Cannot find Typescript module even though tsc successfully manages to resolve it 【发布时间】:2018-11-08 15:57:35 【问题描述】:

我有一个用 Typescript 编写的 Node.js 项目,该项目预计将作为 CLI 运行,并且无法使用绝对路径(相对路径工作正常)导入位于 node_modules 目录之外的模块。值得一提的是,我正在使用 oclif framework 构建我的 CLI。

我的项目组织如下:

cli
 |--node_modules
 |--src
     |--my-module.ts
     |--subdir
          |--index.ts

my-module.ts我有:

 export class MyClass 
     myClassFcn(s: string) 
         return 'result'
     
 

index.ts 脚本包含如下内容:

 import MyClass = require('my-module')

当我尝试使用 ts-node 执行我的应用程序时,我得到了

(node:10423) [MODULE_NOT_FOUND] Error Plugin: cli: Cannot find module 'my-module'
    module: @oclif/config@1.6.17
    task: toCached
    plugin: cli
    root: /home/eschmidt/Workspace/cli
    Error Plugin: cli: Cannot find module 'my-module'
        at Function.Module._resolveFilename (internal/modules/cjs/loader.js:571:15)
        at Function.Module._load (internal/modules/cjs/loader.js:497:25)
        at Module.require (internal/modules/cjs/loader.js:626:17)
        at require (internal/modules/cjs/helpers.js:20:18)
        at Object.<anonymous> (/home/eschmidt/Workspace/cli/src/commands/create/index.ts:5:1)
        at Module._compile (internal/modules/cjs/loader.js:678:30)
        at Module.m._compile (/home/eschmidt/Workspace/cli/node_modules/ts-node/src/index.ts:403:23)
        at Module._extensions..js (internal/modules/cjs/loader.js:689:10)
        at Object.require.extensions.(anonymous function) [as .ts] (/home/eschmidt/Workspace/cli/node_modules/ts-node/src/index.ts:406:12)
        at Module.load (internal/modules/cjs/loader.js:589:32)
    module: @oclif/config@1.6.17
    task: toCached
    plugin: my-plugin
    root: /home/eschmidt/Workspace/cli

我无法理解的是,当我运行 tsc --traceResolution 时,模块已正确解析:

======== Module name 'my-module' was successfully resolved to '/home/eschmidt/Workspace/cli/src/my-module.ts'. ========

我的tsconfig.json 文件包含:


  "compilerOptions": 
    "declaration": true,
    "moduleResolution": "node",
    "forceConsistentCasingInFileNames": true,
    "importHelpers": true,
    "module": "commonjs",
    "sourceMap": true,
    "outDir": "./lib",
    "pretty": true,
    "rootDirs": [
      "./src/"
    ],
    "strict": true,
    "target": "es2017",
    "baseUrl": "src"
  ,
  "include": [
    "./src/**/*"
  ]

如果有人能对这个问题有所了解,或者至少建议在哪里寻求进一步的帮助,我将不胜感激。如果需要更多详细信息,请告诉我。

提前致谢!

【问题讨论】:

您是在subdir 目录中运行ts-node,还是在您的根项目目录中运行tsc?从'../my-module' 导入是否有效? 据我了解,ts-node 是在oclif 框架内注册的,并在我运行/bin 中的sh 脚本并且没有任何转译的JS 时自动调用在lib 目录中。我使用项目根目录中的纱线运行tsc。正如预期的那样,从“../my-module”中的相对路径导入工作正常。 【参考方案1】:

事实证明,问题在于尽管 tsc 和 ts-node 都使用 baseUrl 进行绝对路径解析,但它们都没有在生成的 javascript 代码中执行任何类型的从绝对路径到相对路径的实际映射.换句话说,转译后的 JS 文件和 ts-node 内部生成的代码最终都有:

import  MyClass = require('my-module')

而我期望它们包含类似的内容:

import  MyClass = require('../my-module')

这会阻止节点的模块加载器找到模块。我相信 ts-node 也不起作用,因为根本没有 tsconfig.json 文件来指示路径映射。

尽管 IMO 令人困惑,并且没有正确记录,但这是预期的行为,正如 here 所讨论的那样。截至目前,Typescript 不支持绝对到相对路径的映射(请参阅https://github.com/Microsoft/TypeScript/issues/15479)。

为了避免称为路径地狱的情况,这意味着具有非常深的相对导入路径,我发现module-alias 和tsmodule-alias 非常有用。这些模块改变了模块加载器的行为,以便它自动将别名映射到相对路径。

有关该问题的更多信息,请参阅 Github 上的 issue。

【讨论】:

【参考方案2】:

另一个可能相关的解决方案是使用NODE_PATH=dist node dist/index.js 运行节点。这实质上向node 指定了每个绝对导入(相对于baseUrl)应该使用的路径

【讨论】:

以上是关于即使 tsc 成功解决它,也找不到 Typescript 模块的主要内容,如果未能解决你的问题,请参考以下文章

即使存在,诗歌也找不到依赖的版本

为啥即使创建了对象,django 也找不到与查询匹配的任何对象

即使文件存在,Composer 也找不到 composer.json 文件

即使安装了@types/node,Typescript 也找不到模块“fs”

即使明确提供了模块路径,Eclipse 也找不到模块

即使在调试中,React Native 测试库也找不到文本