首页 > 网页制作 >使用Zod transform为对象添加派生属性

使用Zod transform为对象添加派生属性

来源:互联网 2026-06-24 21:26:05

后端返回的数据里,status 字段是个数字,比如 1,在前端展示时需要转为“OK”、“Unread”这样的文案。如果直接在 Zod schema 中为每个字段添加 .transform() 来派生新属性,容易导致解析报错和类型混乱——Zod 会误以为输入数据中已存在该字段。 核心思路:先定义基础结

后端返回的数据里,status 字段是个数字,比如 1,在前端展示时需要转为“OK”、“Unread”这样的文案。如果直接在 Zod schema 中为每个字段添加 .transform() 来派生新属性,容易导致解析报错和类型混乱——Zod 会误以为输入数据中已存在该字段。

核心思路:先定义基础结构,再整体转换

正确做法是先定义好基础的对象结构,待整个解析完成后再进行整体转换。这样派生字段仅出现在输出侧,不参与输入校验,既干净又安全。

长期稳定更新的攒劲资源: >>>点此立即查看<<<

实现示例

import { z } from 'zod';

export enum ReportMessageStatus {
  UNKNOWN = 0,
  OK = 1,
  UNREAD = 2,
  DELETED = 3,
}

function transformStatus(status: ReportMessageStatus): string {
  switch (status) {
    case ReportMessageStatus.OK:      return 'OK';
    case ReportMessageStatus.UNREAD:  return 'Unread';
    case ReportMessageStatus.DELETED: return 'Deleted';
    default:                          return 'Unknown';
  }
}

//  正确姿势:基础对象 + 整体 .transform()
export const ReportMessageSchema = z
  .object({
    id: z.string(),
    name: z.string(),
    status: z.nativeEnum(ReportMessageStatus),
  })
  .transform((val) => ({
    ...val,
    statusLabel: transformStatus(val.status), // 派生属性,不会出现在输入中
  }));

// 使用示例
const rawData = { id: '203923', name: 'best name', status: 1 };
const parsed = ReportMessageSchema.parse(rawData);
// 类型推导为:{ id: string; name: string; status: ReportMessageStatus; statusLabel: string; }
console.log(parsed.statusLabel); // "OK"

关键要点

  • .transform() 必须挂在完整的 z.object() 实例之后,而非某个字段上——否则会因输入中不存在该字段而直接报错。
  • 派生字段(如 statusLabel)只出现在解析后的输出类型中,输入校验阶段不可见,运行时与类型完全对齐。
  • 如需反向操作(例如提交表单时排除 statusLabel),可组合 .omit({ statusLabel: true }) 生成提交专用的 schema。
  • 复杂转换逻辑建议单独抽成函数并添加 JSDoc 注释,便于后续维护。

总结优势

这种方式保留了 Zod 的强类型约束,同时灵活地为前端 UI 层添加语义字段。简单、可控、符合直觉。

侠游戏发布此文仅为了传递信息,不代表侠游戏网站认同其观点或证实其描述

热游推荐

更多
湘ICP备14008430号-1 湘公网安备 43070302000280号
All Rights Reserved
本站为非盈利网站,不接受任何广告。本站所有软件,都由网友
上传,如有侵犯你的版权,请发邮件给xiayx666@163.com
抵制不良色情、反动、暴力游戏。注意自我保护,谨防受骗上当。
适度游戏益脑,沉迷游戏伤身。合理安排时间,享受健康生活。