在Typescript编译过程中在相对导入语句上附加.js扩展名(ES6模块)

用户名

这似乎是一个琐碎的问题,但是要解决此问题需要使用哪些设置/配置并不是很明显。

这是Hello World程序的目录结构和源代码:

目录结构:

| -- HelloWorldProgram
     | -- HelloWorld.ts
     | -- index.ts
     | -- package.json
     | -- tsconfig.json

index.ts:

import {HelloWorld} from "./HelloWorld";

let world = new HelloWorld();

HelloWorld.ts:

export class HelloWorld {
    constructor(){
        console.log("Hello World!");
    }
}

package.json:

{
  "type": "module",
  "scripts": {
    "start": "tsc && node index.js"
  }
}

现在,执行该命令将tsc && node index.js导致以下错误:

internal/modules/run_main.js:54
    internalBinding('errors').triggerUncaughtException(
                              ^

Error [ERR_MODULE_NOT_FOUND]: Cannot find module 'HelloWorld' imported from HelloWorld\index.js
Did you mean to import ../HelloWorld.js?
    at finalizeResolution (internal/modules/esm/resolve.js:284:11)
    at moduleResolve (internal/modules/esm/resolve.js:662:10)
    at Loader.defaultResolve [as _resolve] (internal/modules/esm/resolve.js:752:11)
    at Loader.resolve (internal/modules/esm/loader.js:97:40)
    at Loader.getModuleJob (internal/modules/esm/loader.js:242:28)
    at ModuleWrap.<anonymous> (internal/modules/esm/module_job.js:50:40)
    at link (internal/modules/esm/module_job.js:49:36) {
  code: 'ERR_MODULE_NOT_FOUND'
}

显然,该问题似乎源于在index.tsTypescript文件.js中import语句(import {HelloWorld} from "./HelloWorld";)中没有扩展名的事实Typescript在编译过程中未引发任何错误。但是,在运行时,节点(v14.4.0)需要.js扩展。

希望背景清楚。

现在,如何更改编译器输出设置(tsconfig.json或任何标志),以使本地相对路径导入(例如import {HelloWorld} from ./Helloworld;import {HelloWorld} from ./Helloworld.js;在Typescript转换为index.js文件中的Javascript期间被替换)

注意: It is possible to directly use the .js extension while importing inside typescript file. However, it doesn't help much while working with hundreds of old typescript modules, because then we have to go back and manually add .js extension. Rather than that for us better solution is to batch rename and remove all the .js extension from all the generated .js filenames at last.

用户名

对于正在寻找此问题的解决方案的其他开发人员,我们遇到的可能的解决方法如下:

  1. 对于新文件,可以".js"在编辑时在Typescript文件的import语句中简单地添加扩展名。例:import {HelloWorld} from "./HelloWorld.js";

  2. 如果使用旧项目,而不是遍历每个文件并更新import语句,我们发现".js"通过简单的自动化脚本简单地批量重命名并从生成的Java脚本中删除扩展名会变得更加容易但是请注意,这可能需要对服务器端代码进行较小的更改,以将这些".js"具有正确MIME类型的无扩展名文件提供给客户端。如果要避免这种情况,可以改用正则表达式批量查找并递归替换import语句以添加.js扩展名。

边注:

关于TS团队在解决此问题上的失败,似乎有一种趋势是试图从实际情况出发,而不是在实际情况中夸大此问题,并将其附加到某些设计原则上加以捍卫。

但是,实际上,这仅是编译器如何不对称地处理extension的问题Typescript编译器允许导入语句而无需扩展。然后,在翻译文件时,它继续在相应的输出文件名中添加“ .js”扩展名,但是对于引用此文件的相应导入语句,它忽略了在翻译过程中添加了“ .js”扩展名的事实。上下文外URI重写原则如何捍卫这种不对称性?

在编译期间,Typescript文件与生成的Javascript输出文件之间存在固定的一对一对应关系。如果引用的导入不存在,则编译器将引发错误。文件甚至无法编译!因此,出于上下文或不可编译的示例,提到其他冲突的URI的可能性会使此类声明无效。

如果编译器仅生成无扩展名的输出文件,那么它也将解决该问题但是,这是否还会以某种方式违反有关URI重写的设计原则?当然,在这种情况下,可能存在其他设计原则来捍卫自己的立场!但是,这样的固执不只是有助于进一步验证TS团队在此问题上的坚定或无知吗?

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章