如何用Zod实现类似TypeScript多接口继承的优雅方案?
使用Zod实现类似TypeScript多接口继承的复合类型
在TypeScript中我们可以通过多接口继承定义复合类型,就像这样:
interface Name { name: string } interface Age { age: number } interface People extends Name, Age { height: number }
要在Zod中实现同样的效果,除了链式调用merge的写法,还有几种更简洁易读的方案:
方案1:利用shape属性+对象展开语法
每个Zod对象Schema都自带shape属性,包含其定义的所有字段规则。我们可以直接将多个基础Schema的shape展开到新的对象Schema中,写法和TS接口继承的逻辑高度一致:
import { z } from "zod"; const nameZ = z.object({ name: z.string() }); const ageZ = z.object({ age: z.number() }); const peopleZ = z.object({ height: z.number(), ...nameZ.shape, ...ageZ.shape, });
这种方式把所有字段规则集中在一起,结构清晰,一眼就能看出peopleZ包含哪些字段。
方案2:先合并基础Schema再扩展新字段
使用Zod的merge先组合基础的类型Schema,再用extend添加新字段,逻辑顺序和TS接口继承完全对应:
import { z } from "zod"; const nameZ = z.object({ name: z.string() }); const ageZ = z.object({ age: z.number() }); const peopleZ = nameZ.merge(ageZ).extend({ height: z.number() });
先合并nameZ和ageZ得到基础的人员属性,再扩展height字段,可读性比多次链式merge更好。
方案3:使用z.intersection(适合强调类型交叉场景)
如果需要明确表达“同时满足多个Schema约束”的复合类型,可以用z.intersection来组合多个对象Schema:
import { z } from "zod"; const nameZ = z.object({ name: z.string() }); const ageZ = z.object({ age: z.number() }); const heightZ = z.object({ height: z.number() }); const peopleZ = z.intersection(z.intersection(nameZ, ageZ), heightZ);
这种写法更偏向“类型交叉”的语义,适合复杂的类型组合场景,不过对于简单的对象字段合并来说,前两种方案更简洁。
内容的提问来源于stack exchange,提问作者Huy Trinh
相关产品推荐
相关产品推荐

