如何在Typescript中导入使用module.exports=的CommonJS模块

22

以下代码可以生成有效的ES5,但是会出现下面的错误。我正在使用Typescript 1.7.5,并且我认为我已经阅读了整个语言规范,但我无法弄清楚为什么会出现这个错误。

error TS2349: Cannot invoke an expression whose type lacks a call signature.

a.js(带有默认导出的ES5环境模块)

function myfunc() {
  return "hello";
}
module.exports = myfunc;
declare module "test" {
    export default function (): string;
}
import test = require("test");
const app = test();

b.js(生成的ES5):

var test = require("test");
var app = test()

这个错误在哪一行? - Cory Danielson
test.ts 文件的第二行。在 test() 函数中。 - drewlio
顺便说一句,你的帖子中使用了基本名称“test”来命名你的三个文件,这相当令人困惑。第三个文件导入了“./test”,并被称为“test.ts”,但它肯定是其他东西。 :) - C Snover
@CSnover 我同意这很不清楚,所以我已经将文件名更改为 aba 是一个没有预先存在的类型声明文件的 ES5 commonjs 模块。 b 是使用 a 的 TypeScript。此外,b.ts 中的 require() 已从 "./test" 更改为 "test",因为它应该是一个外部环境模块的字符串文字。我很惊讶它能够使用 "./test" 作为到 test.js 的相对路径,但它确实可以工作。但这样做更好,因为这是 Typescript 规范中推荐的方式。 - drewlio
1个回答

10

module.exports导出一个CommonJS模块中的字面量值,但export default表示您正在导出一个default属性,这实际上并不是您的JavaScript代码所做的。

在这种情况下,正确的导出语法只是export = myfunc

declare module "test" {
    function myfunc(): string;
    export = myfunc;
}

这个可以。谢谢你。我觉得Typescript规范在这方面把我弄糊涂了。关于导出赋值的部分,它说:“导出赋值存在是为了向后兼容早期版本的Typescript。”(参考链接),暗示这是老的写法,不应该在新的代码中使用导出赋值。这个答案与此紧密相关。 - drewlio
2
另外,对于未来的读者而言,在ES5中module.exports=不是“默认导出”,这是ES6的术语。TypeScript规范在这里解释了default实体。 - drewlio
据我所知,要做到这一点需要在你的TS编译器选项中设置"esModuleInterop": true。或者是我做错了什么? - derpedy-doo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接