基于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
相关产品推荐
相关产品推荐

