从 pg-promise 示例中的'pg-promise'导入 * 作为 pgPromise 会导致打字稿错误 TS2349:此表达式不可调用



在我的程序中调整推荐的typescript示例

import * as pgPromise from 'pg-promise' ;
const pg = pgPromise() ;

不起作用。第二行导致错误:

This expression is not callable. Type 'typeof pgPromise' has no call signatures.ts(2349)

在谷歌上搜索错误消息并没有返回与模块导入相关的答案,因为它们都涉及调用不可调用的对象。然而,我需要一种不同的解释:我不知道为什么import语句会产生一个非函数对象,尽管作者的意图显然是返回一个函数,该函数可以使用多个参数初始化底层模块。

分析模块源代码帮助不大,它是用javascript编写的,看起来不太透明。

这是一个与javascript和ES6规范的转换相关的问题,而不是pg-promise特有的问题。

至少有两种可能的方法来解决这个问题:

  1. 使用不同的语法:
import pgPromise from 'pg-promise' ;

此行按原样导入默认导出对象(在本例中为函数(。它更短,在我看来比下面的行更直观,在示例中使用,并由模块作者推荐:

import * as pgPromise from 'pg-promise' ;

要求,导入的对象是object(因为*表示将其所有属性导入到主命名空间(,因此它确实导入了所有导出的属性,但不导入函数,因为函数没有分配给属性,而是对象本身。

为了更详细地解释差异,

这是一个";普通的";对象:

// module "module-p.js"
let p = { name: 'John', colour: 'blue', age: 1263 }
export default p ;

这是一个具有属性的函数对象:

let p = (x) => { console.log(x); } ;
p.name = 'John';
p.colour = 'blue';
p.age = 1263;
export default p ;

后者,当导入时

import * as P from 'module-p';

将导入对象属性namecolourage并将它们分配给当前命名空间中的对象P。但是,它不会从上面的例子中导入函数p(),因为它在p中没有命名属性;

  1. 快速而肮脏的解决方案是修复tsconfig.json中的选项esModuleInterop
"esModuleInterop": true

"esModuleInterop": false

更改该选项将启用javascript模块pg-promise和其他以类似javascript样式编写的模块所需的宽松模块导入处理。

https://www.typescriptlang.org/tsconfig#esModuleInterop说:

默认情况下(如果esModuleInterop为false或未设置(TypeScript处理的CommonJS/AMD/UMD模块类似于ES6模块。在这样做的过程中,有两个部分被证明是有缺陷的假设:

  • 类似import*的名称空间导入从";时刻";作用与const矩=require("矩"(相同

  • 从";时刻";作用与const moment=require("moment"(相同。默认值

这种不匹配会导致这两个问题:

  • ES6模块规范规定,命名空间导入(import*as x(只能是一个对象,通过让TypeScript将其视为=require("x"(,然后允许TypeScript将导入视为一个函数并可调用。这违反了规范的建议

  • 虽然符合ES6模块规范,但大多数带有CommonJS/AMD/UMD模块的库并不像TypeScript的实现那样严格

pg-promise导入依赖于特定Typescript转译器配置的原因似乎是导出的命名空间是一个函数,而不是对象,这在esModuleInterop = true时是不允许的pg promise文档没有提及任何特定的typescript配置依赖项或要求。

遗憾的是,pg promise的作者决定在这里留下傲慢的评论,而不是在回答中指出打字问题。

最后我自己找到了答案。

示例中有一个错误。原进口报关单:

import * as pgPromise from 'pg-promise' ;

导致错误,如问题中所述。正确的语法是:

import pgPromise from 'pg-promise' ;

然后它按预期工作。

最新更新