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

TypeScript带值枚举使用问题:传入枚举键时Mongoose验证失败

枚举键传入Mongoose模型的验证问题解决

问题描述

使用带值的TypeScript枚举时,想要传入枚举的键(如HA)作为campaign字段值,但触发Mongoose验证错误:

"error": "Appeal validation failed: campaign: \"HA\" is not a valid enum value for path campaign."

尝试将模型中的enum配置改为Object.keys(Campaign)后仍无效,相关代码如下:

相关代码

appealTypes.ts

export enum Campaign {
  E = "Eid",
  R = "Ramadan",
  HA = "Hunger Appeal"
}

export interface Appeal {
  _id: string;
  title: string;
  campaign: Campaign;
}

appealModel.ts

const appealSchema = new mongoose.Schema<Appeal>(
  {
    title: {
      type: String,
      required: true,
    },
    campaign: {
      type: String,
      enum: Object.values(Campaign),
      // required: true,
    },
  },
  { timestamps: true }
);

appealController.ts

const createAppeal = async (request: Request, response: Response) => {
  try {
    const { title, campaign} = request.body;

    const newAppeal = await appealModel.create({
      title, campaign
    });

    response.status(201).json({
      message: "Appeal created successfully",
      data: newAppeal,
    });
  } catch (error) {
    console.error("Error creating appeal:", error);
    response.status(500).json({
      message: "Error creating appeal",
      error: error instanceof Error ? error.message : "Unknown error",
    });
  }
};

问题原因与解决方法

问题核心是TypeScript字符串枚举的双向映射特性,和Mongoose的验证规则不匹配:

  1. 当前模型用Object.values(Campaign)作为枚举值,对应["Eid", "Ramadan", "Hunger Appeal"],但你传入的是枚举键HA,自然不匹配。
  2. 直接用Object.keys(Campaign)会返回["E", "R", "HA", "Eid", "Ramadan", "Hunger Appeal"]——因为TypeScript会为字符串枚举生成双向映射,导致验证逻辑混乱。

正确解决步骤

1. 确定存储规则:存枚举键还是值

如果要存枚举键(E/R/HA):

  • 过滤出枚举的纯键,排除反向映射的值:
// 过滤仅保留枚举的键
const campaignKeys = Object.keys(Campaign).filter(key => isNaN(Number(key)));

const appealSchema = new mongoose.Schema<Appeal>(
  {
    title: { type: String, required: true },
    campaign: {
      type: String,
      enum: campaignKeys, // 此时枚举值为["E", "R", "HA"]
      // required: true,
    },
  },
  { timestamps: true }
);

2. 匹配TypeScript类型

如果存键,需要调整接口类型或在控制器转换:

  • 调整接口类型:
export interface Appeal {
  _id: string;
  title: string;
  campaign: keyof typeof Campaign; // 类型限定为"E"|"R"|"HA"
}
  • 或者在控制器将传入的字符串转为枚举成员:
const newAppeal = await appealModel.create({
  title,
  campaign: Campaign[campaign as keyof typeof Campaign]
});

3. 支持键/值双输入(可选)

如果需要同时兼容传入键或值,可在控制器做前置转换:

let campaignValue: string;
if (Object.keys(Campaign).includes(campaign)) {
  // 传入的是键,转成对应值
  campaignValue = Campaign[campaign as keyof typeof Campaign];
} else if (Object.values(Campaign).includes(campaign)) {
  // 传入的是值,直接使用
  campaignValue = campaign;
} else {
  throw new Error("无效的campaign值");
}

const newAppeal = await appealModel.create({ title, campaign: campaignValue });

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 15:18:18