You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 17:37:05