After examining the type declaration for express-session
, it is clear that it defines a Session
(and modifies the Request
object) within the Express
namespace. By utilizing this, we are able to create a custom type declaration (mySession.dt.s
) to enhance the default properties without running into any issues with declaration merging:
import {Express} from 'express';
import 'express-session';
declare module 'express' {
export interface Request {
session: Express.Session & {
myOwnData: string;
myOwnData2: number;
myOwnData3: boolean;
};
}
}
It is worth noting that the compiler appears to be somewhat flexible regarding imports in this file (such as not requiring explicit import of Express
or
Request</code), but being specific will lead to more consistent results.</p>
<p>Subsequently, we can import this declaration into our server file:</p>
<pre><code>import express = require('express');
import {Express, Request, Response} from 'express';
import './mySession';
import * as session from 'express-session';
const app: Express = express();
const PORT = process.env.PORT || process.env.NODE_PORT || 3000;
app.use('/endpoint', (req: Request, res: Response) => {
const a: number = req.session.myOwnData3 + 2; // triggers compilation error and flagged by text editors
console.log(req.session.myOwnData); // compiles successfully and offers autocomplete in Webstorm
// perform tasks
return res.ok();
});
app.use(session(/** handle session operations **/));
log.info(`Starting Express Server on ${PORT}`);
app.listen(PORT);
As verified through testing, this setup ensures type safety for the added properties and facilitates intellisense/autocomplete in both VSCode and WebStorm for both the original express-session
features and the additional properties.
Regrettably, as mentioned, these modifications do not have global application where type inference is utilized (only when explicitly importing Request
). If complete control over the interface is desired, one option is to uninstall @types/express-session
and manually adjust the d.ts file (and then import it). Alternatively, creating an entirely new property and implementation is possible, but considerably more labor-intensive.