I have an Express.js application written in TypeScript (2.7.1) and I'm trying to dynamically import express-session
module. In my understanding import session from 'express-session'
should be equivalent to let session = await import('express-session')
however the static import work just fine (if express-session
is installed) while the dynamic version complains:
error TS2349: Cannot invoke an expression whose type lacks a call signature.
Type '{ default: typeof session; Store: typeof Store; MemoryStore: typeof MemoryStore; }'
has no compatible call signatures
Here is what my file looks like after removing the static import and surrounding the import with try-catch
:
import express from 'express'
export class MyServer {
public app: express.Application
constructor() {
this.app = express()
this.init()
}
async init() {
try {
const session = await import('express-session')
this.app.use(session({secret: 'my_secure_secret'}))
this.app.set('hasSession', true)
} catch (e) {
console.log('Failed to load session, continue without it')
this.app.set('hasSession', false)
}
}
The import()
function does actually import the whole CommonJS exports
object. Checking the types from @types/express-session
we have:
[...]
declare function session(options?: session.SessionOptions): express.RequestHandler;
declare namespace session {
interface SessionOptions {
secret: string | string[];
name?: string;
store?: Store | MemoryStore;
cookie?: express.CookieOptions;
genid?(req: express.Request): string;
rolling?: boolean;
resave?: boolean;
proxy?: boolean;
saveUninitialized?: boolean;
unset?: string;
}
[...]
export = session;
At this point export = session
actually is equivalent to exports.default = session
(still a bit confusing that compiler understands session
as reference of the function and not as namespace) and this leads to the solution:
async init() {
try {
const session = (await import('express-session')).default
this.app.use(session({secret: 'my_secure_secret'}))
this.app.set('hasSession', true)
} catch (e) {
console.log('Failed to load session, continue without it')
this.app.set('hasSession', false)
}