🔎 搜索词
nodenext, module, __dirname
🕗 版本与回归信息
版本 5.4.5
⏯ Playground链接
- 无响应*
💻 代码
package.json
"type": "module"
tsconfig.json
{
"compilerOptions": {
"module": "NodeNext"
},
"include": ["src"]
}
file.ts
console.log(__dirname)
🙁 实际行为
没有编译器错误,但这会导致Node中的运行时错误:
ReferenceError: __dirname is not defined in ES module scope
🙂 预期行为
编译器应发出类似于反向情况的错误。
例如,针对CommonJS:
package.json
"type": "commonjs"
file.ts
console.log(import.meta.dirname)
编译器会发出以下错误:
error TS1470: The 'import.meta' meta-property is not allowed in files which will build into CommonJS output.
关于问题的附加信息
也许我不明白的原因有一个很好的理由,但我认为 tsc
应该对会产生运行时错误的任何语法发出错误或警告。
这里有一个更完整的示例: https://github.com/knightedcodemonkey/tsc-module-globals
npm install
npm run esm
(注意没有编译错误,但输出导致运行时错误)npm run cjs
(注意确实有编译错误)
5条答案
按热度按时间pobjuy321#
如果在目标为
"type": "module"
时,而使用console.log(globalThis.__dirname)
仍然没有编译错误,并且节点不会抛出关于__dirname
的 ReferenceError,因为它现在是globalThis
的属性。然而,如果你执行console.log(require.main)
,你仍然没有得到编译错误,并且节点会抛出一个关于require
在 ES 模块范围内未定义的 ReferenceError。在这里推荐的使用模式是什么?我知道编写 ES 模块的人经常会这样做:
zy1mlcev2#
这或多或少是可以预料到的,因为这些是由
@types/node
定义为全局的,没有办法说"声明全局,但只有在当前文件是CJS的情况下才生效"。vd8tlhqk3#
感谢反馈。
我想知道为什么编译器不会根据
module
设置和package.json文件中的type
值,引入一些启发式方法来警告在使用CJS全局变量时针对ES模块输出?x6492ojm4#
TS没有“警告”的概念,尽管“建议”诊断很接近。这也是非平凡的,因为人们经常用一种关于转译的假设来编写ESM(但也许想要
typeof require != "undefined"
等),我们还认为任何名为require
的函数在模块解析方面都应被视为require
。如果你符合他们的指南,这里有一些可以严格对待这个问题的lint规则。
fhity93d5#
关于编译器行为的另一个有趣的事情是
给定:
cjs.ts
package.json
file.ts
在
module
的情况下,编译器不会将exports.foo
转换为export const foo
。相反,你会得到此外,没有编译器错误,只有运行时错误。
这是否与 #56678 有关?