Express.js服务器向Redis上传会话数据时遇TypeScript类型错误
问题
在React Native应用用户登录流程中,尝试将会话数据上传至Redis时,执行代码redis.set(user._id, JSON.stringify(user) as any);触发TypeScript错误:
Argument of type 'unknown' is not assignable to parameter of type 'RedisKey'.ts(2345)
(property) Document<unknown, any, any>._id?: unknown This documents _id.
完整代码如下:
require("dotenv").config(); import { Response } from "express"; import { IUser } from "../models/user.model"; import { redis } from "./redis"; import { RedisKey } from "ioredis"; import { ObjectId } from "mongoose"; interface ITokenOptions { expires: Date; maxAge: number; httpOnly: boolean; sameSite: "lax" | "strict" | "none" | undefined; secure?: boolean; } export const sendToken = (user: IUser, statusCode: number, res: Response) => { const accessToken = user.SignAccessToken(); const refreshToken = user.SignRefreshToken(); //upload session to redis redis.set(user._id, JSON.stringify(user) as any); //parse environment variables to integrate with fallback values const accessTokenExpire = parseInt( process.env.ACCESS_TOKEN_EXPIRE || "300", 10 ); const refreshTokenExpire = parseInt( process.env.ACCESS_REFRESH_EXPIRE || "1200", 10 ); //options for cookies const accessTokenOptions: ITokenOptions = { expires: new Date(Date.now() + accessTokenExpire * 1000), maxAge: accessTokenExpire * 1000, httpOnly: true, sameSite: "lax", }; const refreshTokenOptions: ITokenOptions = { expires: new Date(Date.now() + refreshTokenExpire * 1000), maxAge: refreshTokenExpire * 1000, httpOnly: true, sameSite: "lax", }; //only sent secure to true in production if (process.env.NODE_ENV === "production") { accessTokenOptions.secure = true; } res.cookie("access_token", accessToken, accessTokenOptions); res.cookie("refresh_token", refreshToken, refreshTokenOptions); res.status(statusCode).json({ success: true, user, accessToken, }); };
期望实现:将JSON数据成功上传至Redis。
解决方案
1. 规范IUser接口的_id类型(推荐)
问题根源是IUser接口未明确_id的类型,导致TypeScript识别为unknown。修改IUser接口,明确_id为mongoose的ObjectId类型:
// ../models/user.model.ts import { Document, ObjectId } from "mongoose"; export interface IUser extends Document { // 其他字段定义 _id: ObjectId; SignAccessToken(): string; SignRefreshToken(): string; }
然后在sendToken函数中,将_id转为字符串(Redis的key支持字符串类型):
//upload session to redis redis.set(user._id.toString(), JSON.stringify(user));
2. 类型断言(快速临时解决)
如果暂时不想修改接口定义,可以直接对user._id做类型断言,告诉TypeScript它符合RedisKey类型:
//upload session to redis redis.set(user._id as RedisKey, JSON.stringify(user)); // 或者断言为字符串 redis.set(user._id as string, JSON.stringify(user));
3. 处理_id可能为undefined的情况
如果_id存在为undefined的可能,需要加上空值处理,避免运行时错误:
//upload session to redis const redisKey = user._id?.toString() || `user_${Date.now()}`; // 生成临时key作为 fallback redis.set(redisKey, JSON.stringify(user));
内容的提问来源于stack exchange,提问作者Nick Williams
相关产品推荐
相关产品推荐

