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

基于TypeScript枚举定义Mongoose枚举字段的验证问题

解决TypeScript数字枚举在Mongoose Schema中的验证问题

问题原因

TypeScript的数字枚举编译后会生成双向映射的对象,比如你的StatusType枚举编译后会变成:

var StatusType = {
  0: "Decline",
  1: "Approved",
  Approved: 1,
  Decline: 0
};

使用Object.values(StatusType)会同时返回数字值和枚举名称字符串:[1, 0, "Approved", "Decline"]。当Mongoose字段类型设为Number时,枚举数组中混入的字符串会导致验证逻辑异常,触发验证错误。

解决方案

方案1:过滤枚举值,只保留数字类型

手动过滤Object.values的结果,仅保留数字类型的枚举值:

enum StatusType {
    Approved = 1,
    Decline = 0,
}

// 过滤出纯数字的枚举值
const validStatusValues = Object.values(StatusType).filter(v => typeof v === 'number') as number[];

const userSchema = new Schema({
  user: { type: Schema.Types.ObjectId, ref: 'User' },
  statusType: {
    type: Number,
    default: StatusType.Approved,
    enum: validStatusValues
  }
});

方案2:手动指定枚举值数组

直接使用枚举成员构建数组,避免引入反向映射的字符串:

enum StatusType {
    Approved = 1,
    Decline = 0,
}

const userSchema = new Schema({
  user: { type: Schema.Types.ObjectId, ref: 'User' },
  statusType: {
    type: Number,
    default: StatusType.Approved,
    enum: [StatusType.Approved, StatusType.Decline]
  }
});

方案3:使用const enum(可选)

如果你的枚举不需要在运行时访问枚举名称,可以使用const enum,它编译后不会生成反向映射,Object.values只会返回数字值:

const enum StatusType {
    Approved = 1,
    Decline = 0,
}

const userSchema = new Schema({
  user: { type: Schema.Types.ObjectId, ref: 'User' },
  statusType: {
    type: Number,
    default: StatusType.Approved,
    enum: Object.values(StatusType)
  }
});

注意:const enum只能在TypeScript中使用,编译后会被替换为具体数值,无法在运行时动态获取枚举成员。

验证效果

使用以上方案后,Mongoose会正确验证数字类型的statusType字段,保存到数据库的是数字1或0,同时能利用TypeScript的枚举类型检查避免代码中的类型错误。

内容的提问来源于stack exchange,提问作者davies

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 10:31:12