TypeScript 版本: 2.7.2
搜索词: esModuleInterop, esnext, modules, import, export, default
代码
使用这个类型定义:
declare function fn(): void;
declare module "external" {
export = fn;
}
运行时:
tsc --esModuleInterop --module esnext
导入时产生以下错误:
import fn1 from 'external'; // error TS1192: Module '"external"' has no default export.
import fn2 = require('external'); // error TS1202: Import assignment cannot be used when targeting ECMAScript modules.
但是,如果你使用 CommonJS 模块:
tsc --esModuleInterop --module commonjs
它按预期工作(因为 --esModuleInterop
)
import fn1 from 'external'; // works
import fn2 = require('external'); // works
预期行为:
可以理解的是,当它不在 helpers 中编译时,类型检查器不想假装导入是 interop'd。
但是,如果你已经指定了 --esModuleInterop
和 --module esnext
,那么类型检查器的假设应该是外部系统正在应用 interop。否则,你为什么要指定 --esModuleInterop
呢?
Playground 链接:https://github.com/jamiebuilds/ts-bug
9条答案
按热度按时间flvlnr441#
这个问题实际上是关于到底要发出什么内容。当你想要将内容发出到ES模块时,一个默认的导入确实需要继续保持为默认导入。因此,
esModuleInterop
既涉及到类型检查,也涉及到默认值。另一方面,当你期望外部工具(例如Babel、Webpack、SystemJS)自行拼接ES互操作性时,这时你可以使用
allowSyntheticDefaultImports
。我想你可以提出这样的观点:
esModuleInterop
应该暗示allowSyntheticDefaultImports
并只发出空内容,但@weswigham可能有更好的见解。mfpqipee2#
--allowSyntheticDefaultImports
的问题在于它仍然将import * as foo from 'cjs'
视为与import foo from 'cjs'
相同。理想情况下的行为应该是类似于"--requireSyntheticDefaultImports"。nkkqxpd93#
我猜你可以提出这样的观点:esModuleInterop应该暗示允许合成默认导入
@DanielRosenwasser 它不是已经实现了吗?来自
--esModuleInterop
docsjecbmhm34#
allowSyntheticDefaultImports
无法解决这个问题。当你重新导出使用它导入的内容时,它还具有破坏性行为:你得到一个形状为{ default: T }
的对象,而不是T
daupos2t5#
请注意,Node 12.x 仅在从 ESModules 导入 CommonJS 模块时支持
default
导入:这不起作用:
唯一例外的是内置模块,它们有特殊的处理方式。
carvr3hs6#
这个问题似乎在TypeScript 3.2、3.1或更高版本中已经解决了。
bvjxkvbb7#
你好,请问这个问题已经解决了吗?我遇到了一个类似的问题,就像@jamiebuildshere提到的那样。
我正在使用一个库,它导出一个名为
default
的函数。当我导入这个对象时,根据我的 TypeScript 项目是设置为esm
还是commonjs
,我会得到两个不同的对象表示。项目沙箱可以在 here 找到。
TypeScript 项目设置为 commonjs
"type": "commonjs"
在package.json
"module": "commonjs"
在tsconfig.json
node -r ts-node/register src/index.ts
[Function: standaloneCode]
,这是预期的输出TypeScript 项目设置为 esm
"type": "module"
在package.json
"module": "esnext"
在tsconfig.json
node --loader ts-node/esm src/index.ts
{ default: [Function: standaloneCode] }
。这弄乱了我的类型定义。我已经尝试过使用
"esModuleInterop": true
和"allowSyntheticDefaultImports": true
,但似乎没有太大的区别。如果有任何解决方法或建议,我将非常感激。
6uxekuva8#
你的这个问题与这个issue不同。这是当前TypeScript规范的问题。
ajv的
main
具有a special hack,使其从TS commonjs和esm中都可读,https://github.com/ajv-validator/ajv/blob/8ffe5faca9c4b49fc538b35399a1b4febba0bc41/lib/ajv.ts#L34-L35
但是你的
ajv/dist/standalone/index.js
没有这样的技巧。https://github.com/ajv-validator/ajv/blob/8ffe5faca9c4b49fc538b35399a1b4febba0bc41/lib/standalone/index.ts
mcdcgff09#
感谢@teppeis。明白了。我会在
ajv
仓库中提出这个问题。