Zod是否可以直接从类型`Person`中推导后进行验证呢?

现有一个类型:

interface Person {
age: number,
name: string,
desc?: string
}

现在写了一个接口:
想要使用zod进行验证参数:
我只会这样写:

z.object({
  age: z.number(),
  name: z.string(),
  desc: z.string().optional()
})

这样感觉比较繁琐,要对Person的字段重复写一遍,请问是否有其他简单方式呢?比如直接从Person中推导后进行验证即可。

阅读 393
avatarAI BotBETA
是的,Zod 提供了从 TypeScript 类型直接推导并创建 schema 的功能,这样可以避免手动重复定义字段。你可以使用 `z.infer<T>()` 结合 `z.object().shape()` 和 TypeScript 的类型映射来实现这一点。不过需要注意的是,`z.infer<T>()` 通常用于从已有的 Zod schema 中推导类型,而不是直接从 TypeScript 类型推导 Zod schema。但你可以通过一些技巧来实现类似的效果。

为了直接从 `Person` 类型推导 Zod schema,你可以创建一个辅助函数来自动生成 schema。以下是一个示例:

import * as z from 'zod';

interface Person {
age: number;
name: string;
desc?: string;
}

type PersonSchema = z.infer<z.TypeOf<typeof createPersonSchema>>;

const createPersonSchema = () =>
z.object({

age: z.number(),
name: z.string(),
desc: z.string().optional(),

}) as const; // 使用 as const 确保类型被正确推断为只读

// 使用推导的 schema
const personSchema = createPersonSchema();

// 示例验证
const validPerson = personSchema.parse({ age: 30, name: 'John Doe' });
const invalidPerson = personSchema.safeParse({ age: 'not a number', name: 'John Doe' });

console.log(validPerson); // 成功解析的对象
console.log(invalidPerson.success); // false,因为 age 不是数字


虽然上面的代码看起来还是手动定义了 schema,但它被封装在了一个函数中,你可以根据接口的变化只需要修改一个地方。

目前,Zod 并没有直接提供从 TypeScript 接口自动转换到 Zod schema 的内置功能,因为 TypeScript 类型系统和 Zod schema 是两个不同的系统,它们之间有一些不匹配的地方。但是,你可以使用 TypeScript 的工具类型和一些模板字面量类型技巧来减少重复代码。

如果你的接口非常复杂或者有很多这样的接口需要转换,考虑编写一个更通用的工具函数或脚本,根据你的 TypeScript 类型生成相应的 Zod schema 代码。
1 个回答
新手上路,请多包涵

先定义 schema,然后从 schema 推导出 interface:

import { z } from 'zod';

// 1. 定义 schema
const PersonSchema = z.object({
  age: z.number(),
  name: z.string(),
  desc: z.string().optional(),
});

// 2. 推导出 interface
type Person = z.infer<typeof PersonSchema>;

这种方式的优点:
避免重复定义
类型和验证规则保持同步
代码更简洁易维护
符合 "单一数据源" 的原则
这样你只需要维护 schema,TypeScript 类型会自动推导出来。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
logo
Microsoft
子站问答
访问
宣传栏