This is an issue related to transpilation to javascript and ES6 specification, not specific to pg-promise
.
There are at least two possible ways how to solve this issue:
- Use different syntax:
import pgPromise from 'pg-promise' ;
This line imports the default export object (in this case function) as-is. It is shorter, and, in my opinion more intuitive than the following line, used in the example and recommended by module author:
import * as pgPromise from 'pg-promise' ;
requires, that the imported object is an Object (because * means importing all of its properties to the main namespace) and therefore it does import all exported properties, but not the function, because the function is not assigned to a property, it is the object itself.
To explain the difference in more detail,
This is a "plain" object:
// module "module-p.js"
let p = { name: 'John', colour: 'blue', age: 1263 }
export default p ;
and this is a function object with properties:
let p = (x) => { console.log(x); } ;
p.name = 'John';
p.colour = 'blue';
p.age = 1263;
export default p ;
The latter, when imported by
import * as P from 'module-p';
will import object properties name
, colour
and age
and assign them to object P
in the current namespace. However, it will not import function p()
from the above example, because it has no named property in p
;
- Quick and dirty solution is to fix option
esModuleInterop
in tsconfig.json
:
"esModuleInterop": true
to
"esModuleInterop": false
Changing the option will enable the relaxed module import handling needed for the javascript module pg-promise
and other modules written in similar javascript style.
https://www.typescriptlang.org/tsconfig#esModuleInterop says:
By default (with esModuleInterop false or not set) TypeScript treats CommonJS/AMD/UMD modules similar to ES6 modules. In doing this, there are two parts in particular which turned out to be flawed assumptions:
a namespace import like import * as moment from "moment" acts the same as const moment = require("moment")
a default import like import moment from "moment" acts the same as const moment = require("moment").default
This mis-match causes these two issues:
the ES6 modules spec states that a namespace import (import * as x) can only be an object, by having TypeScript treating it the same as = require("x") then TypeScript allowed for the import to be treated as a function and be callable. This breaks the spec’s recommendations.
while accurate to the ES6 modules spec, most libraries with CommonJS/AMD/UMD modules didn’t conform as strictly as TypeScript’s implementation.
The reason why pg-promise
import depends on particular Typescript transpiler configuration appears to be that the exported namespace is a function, not an object, which is not allowed when esModuleInterop = true
. pg-promise documentation does not mention any specific typescript configuration dependencies or requirements.
Sadly, the author of pg-promise decided to leave arrogant comments here instead of pointing the typescript issue in an answer.