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

如何用Zod为TypeScript类型创建Schema及扩展外部类型?

Zod 常见问题解答:类型到Schema的转换与外部类型集成

1. 如何使用Zod为任意TypeScript类型创建Schema?

Zod提供了直观的API来映射不同的TypeScript类型,以下是常见场景的实现方式:

  • 基础类型:直接使用Zod内置的对应方法,比如z.string()对应string,z.number()对应number,z.boolean()对应boolean等。
  • 联合类型/字面量类型:用z.union()组合多个字面量schema,或者更简洁的z.enum:
type Status = "pending" | "success" | "failed";
// 方式1:union + literal
const statusSchema = z.union([z.literal("pending"), z.literal("success"), z.literal("failed")]);
// 方式2:直接用enum
const statusSchema = z.enum(["pending", "success", "failed"]);
  • 对象接口/类型别名:用z.object()定义结构,嵌套对应字段的schema:
interface User {
  name: string;
  age: number;
  isActive: boolean;
}
const userSchema = z.object({
  name: z.string(),
  age: z.number().min(18),
  isActive: z.boolean()
});
// 也可以从schema反向推导类型:type User = z.infer<typeof userSchema>
  • 复杂集合类型:结合z.array()、z.record()、z.tuple()等方法处理数组、记录、元组:
type UserList = User[];
const userListSchema = z.array(userSchema);

type UserMap = Record<string, User>;
const userMapSchema = z.record(z.string(), userSchema);

2. 如何将Zod的类型系统与外部接口/类型进行扩展?

你用z.custom<MyType>()未达预期,核心原因是**z.custom默认仅做TypeScript层面的类型断言,没有运行时校验逻辑**——Zod无法自动识别外部类型的结构,必须手动补充验证规则。以下是几种可靠的解决方案:

方案1:为z.custom添加运行时校验逻辑

如果清楚MyType的运行时特征,在z.custom中传入验证函数,确保数据符合类型要求:

import * as z from 'zod'
import { MyType } from './myType'

// 假设MyType是包含id(数字)和name(字符串)的对象
const mySchema = z.object({
  custom: z.custom<MyType>((val) => {
    return typeof val === 'object' && val !== null 
      && 'id' in val && typeof val.id === 'number'
      && 'name' in val && typeof val.name === 'string';
  }, {
    message: "输入不符合MyType的结构要求" // 自定义错误提示
  })
})

方案2:基于外部类型结构构建匹配的Zod Schema

如果MyType是接口或类型别名,直接用Zod的基础API拼接出对应schema,还可以通过类型断言确保编译时类型一致:

import * as z from 'zod'
import { MyType } from './myType'

// 按照MyType的字段定义对应的schema
const myTypeSchema = z.object({
  foo: z.string(),
  bar: z.number().positive()
})

// 编译时校验:确保schema推导的类型与MyType匹配(不匹配则报错)
type _AssertMatch = z.infer<typeof myTypeSchema> extends MyType ? true : never;

const mySchema = z.object({
  custom: myTypeSchema
})

方案3:类类型用z.instanceof

如果MyType是Class(而非接口/类型别名),直接使用z.instanceof即可:

import * as z from 'zod'
import { MyType } from './myType' // 这里MyType是类

const mySchema = z.object({
  custom: z.instanceof(MyType)
})

方案4:用z.refine做类型窄化

如果已有一个基础schema,需要将其窄化为外部类型,可使用z.refine配合类型谓词:

import * as z from 'zod'
import { MyType } from './myType'

const mySchema = z.object({
  custom: z.any().refine((val): val is MyType => {
    // 这里编写验证逻辑,返回true则Zod会将val的类型断言为MyType
    return /* 验证val符合MyType结构的逻辑 */;
  })
})

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 04:44:53