使用express-session结合Redis Store时遇TypeScript错误求助
解决Express-Session + Redis Store的TypeScript错误
问题根源
connect-redis v7及以上版本的API做了变更:不再通过new RedisStore()实例化存储对象,而是直接调用导出的工厂函数;同时TypeScript类型定义需要更明确的关联,否则会出现构造签名缺失、属性不存在的错误。
方案1:使用官方Redis客户端(redis@4+ + connect-redis@7+)
修正后的完整代码:
import express, { Request } from "express"; import { expressMiddleware } from "@apollo/server/express4"; import startApolloServer from "./graphql"; import RedisStore from "connect-redis"; import session from "express-session"; import { createClient } from "redis"; async function init() { const app = express(); // 创建Redis客户端,可根据需要添加连接配置(如url、密码) const redisClient = createClient(); redisClient.connect().catch(console.error); // connect-redis v7+ 直接调用工厂函数,无需new const redisStore = RedisStore({ client: redisClient, prefix: "myapp-session:", // 可选:给session键名加前缀,避免和其他Redis数据冲突 }); // 扩展Request类型,让TypeScript识别req.session属性 const context = async ({ req }: { req: Request & { session: session.Session } }) => ({ session: req.session, }); app.use(express.json()); app.use( session({ store: redisStore, name: "connect.sid", secret: process.env.SESSION_SECRET || "dev-secret", // 生产环境建议用环境变量存密钥 resave: false, saveUninitialized: false, cookie: { httpOnly: true, secure: process.env.NODE_ENV === "production", // 生产环境开启HTTPS时设为true sameSite: "lax" as const, // 明确类型避免TS报错 maxAge: 1000 * 60 * 60 * 24 * 7, // 7天有效期 }, }) ); app.use( "/graphql", expressMiddleware(await startApolloServer(), { context }) ); app.listen(4000, () => { console.log("Server running on port 4000: http://localhost:4000/graphql"); }); } init();
方案2:使用ioredis客户端
如果习惯用ioredis,按以下方式调整:
import express, { Request } from "express"; import { expressMiddleware } from "@apollo/server/express4"; import startApolloServer from "./graphql"; import session from "express-session"; import Redis from "ioredis"; import RedisStore from "connect-redis"; async function init() { const app = express(); // 创建ioredis客户端 const redisClient = new Redis({ host: "localhost", // 按需配置Redis地址 port: 6379, }); // 同样直接调用RedisStore工厂函数 const redisStore = RedisStore({ client: redisClient, }); // 扩展SessionData类型,定义你的session数据结构(可选但推荐) declare module "express-session" { interface SessionData { userId?: string; // 其他你需要存在session里的字段 } } const context = async ({ req }: { req: Request }) => ({ session: req.session, }); app.use(express.json()); app.use( session({ store: redisStore, name: "connect.sid", secret: process.env.SESSION_SECRET || "dev-secret", resave: false, saveUninitialized: false, cookie: { httpOnly: true, secure: process.env.NODE_ENV === "production", sameSite: "lax" as const, maxAge: 1000 * 60 * 60 * 24 * 7, }, }) ); app.use( "/graphql", expressMiddleware(await startApolloServer(), { context }) ); app.listen(4000, () => { console.log("Server running on port 4000: http://localhost:4000/graphql"); }); } init();
核心修复点
- 移除
new关键字:connect-redis v7+ 导出的是工厂函数,直接调用即可,解决TS7009构造签名缺失错误 - 类型扩展:通过
Request & { session: session.Session }或扩展SessionData接口,让TypeScript正确识别session属性 - 参数类型修正:
sameSite用as const明确类型,避免TS报错 - 安全优化:用环境变量存储session密钥,不要硬编码在代码中
内容的提问来源于stack exchange,提问作者Varun Panyam
相关产品推荐
相关产品推荐

