Reputation: 9084
I know this is not an actual issue, but a help wanted.
I'm struggling with typescript and express session and I have been playing around and trying to fiugure out this one for quite a bit.
I'm trying to extend my session object, for that, I'm trying to do a merge of typings as per in the documentation:
I have a types/session.d.ts
with the following interface to be merged:
declare module 'express-session' {
interface SessionData {
userId: string;
}
}
But this is not working, as an example, in other-folder/some.ts
req.session.userId = user.id;
// Property 'userId' does not exist on type 'Session & Partial<SessionData>'.
However, if I import Session
from express-session
, it does work:
import { Session } from 'express-session'
declare module 'express-session' {
interface SessionData {
userId: string;
}
}
I'm not very proficient with TypeScript and I'm unsure about importing a module in a type defintion, event TypeScript complains about this (warning):
'Session' is declared but its value is never read.
I'm wondering, is this the right way of tackling the problem?
What can I do different?
Kind regards!
PS: my tsconfig should be fine as I have available through my code other type definitions and they are working with no issues at all.
Upvotes: 3
Views: 3798
Reputation: 344
For whatever reason, declaring the module in .d.ts file still failed to load the custom variable on the session during compilation, vscode intellisense detected it to be correct. What worked for me was to declare the module in the entry file as such `
import express from "express"
const app = express()
declare module 'express-session' {
interface SessionData {
data: string
}
}
app.get("/", your routes here)
app.listen(8000)
` I hope this helps someone in the future.
Upvotes: 0
Reputation: 102547
You should use Module Augmentation. You should also know this from Modules:
In TypeScript, just as in ECMAScript 2015, any file containing a top-level import or export is considered a module. Conversely, a file without any top-level import or export declarations is treated as a script whose contents are available in the global scope (and therefore to modules as well).
For example:
./src/main.ts
:
import express from 'express';
import session from 'express-session';
const app = express();
app.use(
session({
secret: 'keyboard cat',
resave: false,
saveUninitialized: true,
cookie: { secure: true },
}),
);
app.get('/', (req, res) => {
const user = { id: '1' };
req.session.userId = user.id;
});
./types/session.d.ts
: Make sure you include at least one top-level import
or export
to make this file as a module, NOT a script whose contents are available in the global scope. Sometimes, you will import and use some interfaces or types from third-party node modules. But in your case, you don't need it. So just use export {}
or import 'express-session'
, both of them are ok.
declare module 'express-session' {
interface SessionData {
userId: string;
}
}
export {};
tsconfig.json
:
"typeRoots": [
"./node_modules/@types",
"./types",
],
package versions:
"express": "^4.17.1",
"@types/express": "^4.17.11",
"typescript": "^3.9.7"
"express-session": "^1.17.1",
"@types/express-session": "^1.17.3",
Upvotes: 7