如何在Zod共享类型文件中实现前后端字段差异化验证?
实现前后端共享类型的选择性验证
要在同一类型文件中让_id字段在后端作为ObjectId验证、前端作为String验证,可以通过环境条件判断结合Zod的schema实现,具体方案如下:
核心思路
利用前后端运行环境的差异(Node.js vs 浏览器),通过条件分支选择对应的Zod验证规则,同时保证类型推断自动适配两端需求。
具体实现
1. 基于环境变量的条件判断
修改现有代码,添加环境分支逻辑:
import { z } from "zod"; import { ObjectId } from "bson"; // 根据环境选择对应的ID验证规则 const idValidationSchema = typeof process !== "undefined" && process.env.IS_SERVER === "true" // 后端:验证并转换为ObjectId ? z.custom<ObjectId>().transform((value) => new ObjectId(value)) // 前端:验证为字符串 : z.string(); // 定义BaseObject schema export const BaseObject = z.object({ _id: idValidationSchema.optional(), }); // 导出自动推断的类型 export type BaseObject = z.infer<typeof BaseObject>;
2. 配置环境变量(可选优化)
为了更精准区分前后端,可通过构建工具注入环境变量:
- 后端Node环境:在启动脚本中设置
IS_SERVER=true(比如cross-env IS_SERVER=true node server.js) - 前端构建工具(如Vite/Webpack):注入
IS_SERVER=false的全局变量,简化判断逻辑
以Vite为例,在vite.config.js中添加:
export default { define: { IS_SERVER: JSON.stringify(false), }, };
此时代码可简化为:
const idValidationSchema = IS_SERVER ? z.custom<ObjectId>().transform((value) => new ObjectId(value)) : z.string();
效果说明
- 后端环境:
_id字段会被验证为合法的ObjectId格式,并转换为ObjectId实例,类型推断结果为ObjectId | undefined - 前端环境:
_id字段仅需符合字符串格式,类型推断结果为string | undefined - 前端无需额外处理
bson包,构建工具会自动tree-shaking掉未使用的ObjectId相关代码
内容的提问来源于stack exchange,提问作者Andy P
相关产品推荐
相关产品推荐

