教程 zod tutorial

类型推断

Zod 提供了强大的类型推断功能,可以从模式定义中自动推断出 TypeScript 类型。

基本类型推断

ts
import { z } from "zod";

// 基本类型
const stringSchema = z.string();
type StringType = z.infer<typeof stringSchema>; // string

const numberSchema = z.number();
type NumberType = z.infer<typeof numberSchema>; // number

const booleanSchema = z.boolean();
type BooleanType = z.infer<typeof booleanSchema>; // boolean

对象类型推断

ts
const UserSchema = z.object({
  id: z.string(),
  name: z.string(),
  age: z.number().optional(),
  email: z.string().email(),
});

type User = z.infer<typeof UserSchema>;
// {
//   id: string;
//   name: string;
//   age?: number;
//   email: string;
// }

数组和元组类型推断

ts
// 数组
const stringArraySchema = z.array(z.string());
type StringArray = z.infer<typeof stringArraySchema>; // string[]

// 元组
const tupleSchema = z.tuple([z.string(), z.number(), z.boolean()]);
type Tuple = z.infer<typeof tupleSchema>; // [string, number, boolean]

联合和交叉类型

ts
// 联合类型
const unionSchema = z.union([z.string(), z.number()]);
type Union = z.infer<typeof unionSchema>; // string | number

// 交叉类型
const intersectionSchema = z.intersection(
  z.object({ name: z.string() }),
  z.object({ age: z.number() })
);
type Intersection = z.infer<typeof intersectionSchema>;
// { name: string } & { age: number }

递归类型推断

ts
const CategorySchema: z.ZodType<Category> = z.lazy(() =>
  z.object({
    name: z.string(),
    subcategories: z.array(CategorySchema),
  })
);

type Category = z.infer<typeof CategorySchema>;
// {
//   name: string;
//   subcategories: Category[];
// }

Promise 类型推断

ts
const AsyncSchema = z.promise(z.string());
type AsyncType = z.infer<typeof AsyncSchema>; // Promise<string>

const ComplexAsyncSchema = z.promise(
  z.object({
    data: z.array(z.string()),
  })
);
type ComplexAsync = z.infer<typeof ComplexAsyncSchema>;
// Promise<{ data: string[] }>

枚举类型推断

ts
// Zod 枚举
const ZodEnum = z.enum(["A", "B", "C"]);
type ZodEnumType = z.infer<typeof ZodEnum>; // "A" | "B" | "C"

// 原生枚举
enum NativeEnum {
  A = "A",
  B = "B",
  C = "C",
}
const NativeEnumSchema = z.nativeEnum(NativeEnum);
type NativeEnumType = z.infer<typeof NativeEnumSchema>; // NativeEnum

类型转换

ts
const StringToNumber = z.string().transform(val => parseFloat(val));
type TransformedType = z.infer<typeof StringToNumber>; // number

const ComplexTransform = z
  .object({
    values: z.array(z.string()),
  })
  .transform(obj => ({
    numbers: obj.values.map(Number),
  }));
type ComplexTransformed = z.infer<typeof ComplexTransform>;
// { numbers: number[] }

实际应用

ts
// API 响应类型
const ApiResponse = z.object({
  success: z.boolean(),
  data: z.union([
    z.object({
      users: z.array(
        z.object({
          id: z.string(),
          name: z.string(),
        })
      ),
    }),
    z.object({
      error: z.string(),
    }),
  ]),
});

type ApiResponseType = z.infer<typeof ApiResponse>;
// {
//   success: boolean;
//   data: {
//     users: { id: string; name: string; }[];
//   } | {
//     error: string;
//   };
// }

// 使用推断的类型
async function fetchUsers(): Promise<ApiResponseType> {
  // 实现...
  return {
    success: true,
    data: {
      users: [
        { id: "1", name: "张三" },
        { id: "2", name: "李四" },
      ],
    },
  };
}