Even though I love Lin Du's answer, It might not work for usecases where you may have different Session type for different requests (one for user facing, one for admin panel, etc. -- In this case the session object is not constant)
I ended up creating CustomRequestHandlers to handle different type of Session types instead.
import session from 'express-session';
import { ParamsDictionary } from 'express-serve-static-core';
import { ParsedQs } from 'qs';
import { NextFunction, Request, RequestHandler, Response } from 'express';
interface CustomUserSession extends session.Session {
user: {
username: string;
};
}
interface RequestWithSession<
P = ParamsDictionary,
ResBody = any,
ReqBody = any,
ReqQuery = ParsedQs,
LocalsObj extends Record<string, any> = Record<string, any>,
> extends Request<P, ResBody, ReqBody, ReqQuery, LocalsObj> {
session: CustomUserSession;
}
export interface UserReqHandler<
P = ParamsDictionary,
ResBody = any,
ReqBody = any,
ReqQuery = ParsedQs,
LocalsObj extends Record<string, any> = Record<string, any>,
> extends RequestHandler {
(req: RequestWithSession<P, ResBody, ReqBody, ReqQuery, LocalsObj>, res: Response<ResBody, LocalsObj>, next: NextFunction): void;
}
Once this was done I would just use it this way
export const handleUserAuth: UserReqHandler = async (req, res, next) => {
req.session.user = {
username: 'foo', // No Type errors.
};
}
We can then create multiple Req Handlers based on our requirements.
Session
instance has this user property, but in reality (at run time) that won't be the case. Express will execute your function and they will pass a request which has a session, but this session won't have this user. β Chelyuskin