@coji/zodix

中文文档
0.7.0发布于 2025/11/01MITTypeScriptESM + CJS零依赖构建来源已验证近 30 天下载 2292

与 Zod 解析回放路由器加载器和动作

中文使用文档
文档目录27 节
  1. 要点
  2. 设置
  3. Zod 版本兼容性
  4. 移徙指南
  5. 使用量
  6. zx.parse-Params(参数:params,计划:Schema)
  7. zx.parseForm( 请求: 请求, 计划: Schema)
  8. zx.parse查询(请求:请求,计划:Schema)
  9. zx.parseParamsSafe () / zx.parseFormSafe () / zx.parseQuery…
  10. 处理错误
  11. parseParams() , (中文(简体) ), parseForm() ,以及 parseQuery()
  12. parseParamsSafe() , (中文(简体) ), parseFormSafe() ,以及 parseQue…
  13. 动态图
  14. 类型推论帮助器
  15. 以 z.obobject (. extend () 构建动态形状
  16. 备选办法
  17. 援助者 Zod Schemas
  18. 可用的助手
  19. 使用量
  20. Zod v3/v4 兼容性细节
  21. 如何运作
  22. 与 Zod v3 使用
  23. 与 Zod v4 使用
  24. 额外
  25. 自定义 URLSearchParams 解析
  26. 有多重意图的行动
  27. 承认

佐迪克斯语Name

Build Status npm version

佐迪克斯是一个集合 佐德语Name 水电费 反应路由器 v7 装载器和动作。 它总结了解析和验证的复杂性 FormData 财务报告和审定财务报表 URLSearchParams 所以,你的装载器/动作保持干净 并强烈地打字.

现在全力支持Zod v3和v4!

有反应的路由器加载器往往看起来像:

export async function loader({ params, request }: Route.LoaderArgs) {
  const { id } = params
  const url = new URL(request.url)
  const count = url.searchParams.get('count') || '10'
  if (typeof id !== 'string') {
    throw new Error('id must be a string')
  }
  const countNumber = parseInt(count, 10)
  if (isNaN(countNumber)) {
    throw new Error('count must be a number')
  }
  // Fetch data with id and countNumber
}

这是和Zodix相同的装载器:

export async function loader({ params, request }: Route.LoaderArgs) {
  const { id } = zx.parseParams(params, { id: z.string() })
  const { count } = zx.parseQuery(request, { count: zx.NumAsString })
  // Fetch data with id and count
}

检查 示例应用程序 用于完整的常见模式实例.

要点

  • 完全 Zod v3 和 v4 兼容性 - 与两个版本无缝工作
  • 动态计划支持 - 根据数据库/API数据在运行时建立计划
  • 大幅降低回放路由器动作/装入器 bloat
  • 避免 FormData 和 URLSearchParams 的异常
  • 无外部依赖的微小( N)不足 1kb 克齐克(中文(简体) )
  • 使用现有的 Zod 策略, 或者在苍蝇上写入
  • 自定义字符串数字、布尔和复选框的 Zod 方案
  • 默认情况下丢出用于 React 路由器错误边界的错误
  • 支持对自定义验证/错误进行非抛出解析
  • 与所有 React 路由器运行时间( 节点、 Deno、 Vercel、 Cloudflare等) 一起工作
  • 满 单位测试覆盖率

设置

安装 npm, 纱线, pnpm等 .

npm install @coji/zodix zod

Zod 版本兼容性

Zodix通过单独的导入路径支持Zod v3和v4:

  • Zod v3 (英语): 使用 @coji/zodix (所需经费) zod@^3.25.0 (或后来)
  • 佐德 v4 (英语): 使用 @coji/zodix/v4 (所需经费) zod@^4.0.0(中文(简体) )
// For Zod v3
import { zx } from '@coji/zodix'

// For Zod v4
import { zx } from '@coji/zodix/v4'

移徙指南

从 Zod v3 升级到 v4 ? 遵循这些步骤:

  1. 更新您的 Zod 依赖 : npm install zod@^4.0.0
  2. 必要时审查并迁移您的 Zod 计划 - 看 Zod v4 更改日志 用于断开更改
  3. 更改您的 Zodix 从 @coji/zodix 改为 @coji/zodix/v4
  4. 就这样

使用量

导入 zx 对象,或特定函数:

import { zx } from '@coji/zodix'
// import { parseParams, NumAsString } from '@coji/zodix';

zx.parse-Params(参数:params,计划:Schema)

分析并验证 Params 对象从 Route.LoaderArgs['params'] 或者说 Route.ActionArgs['params'] 使用 Zod 形状:

export async function loader({ params }: Route.LoaderArgs) {
  const { userId, noteId } = zx.parseParams(params, {
    userId: z.string(),
    noteId: z.string(),
  })
}

与以上相同,但使用已存在的 Zod 对象方案:

// This is if you have many pages that share the same params.
export const ParamsSchema = z.object({ userId: z.string(), noteId: z.string() })

export async function loader({ params }: Route.LoaderArgs) {
  const { userId, noteId } = zx.parseParams(params, ParamsSchema)
}

zx.parseForm( 请求: 请求, 计划: Schema)

解析和验证 FormData 从a Request 在回放路由器动作中避免乏味 FormData 舞会:

export async function action({ request }: Route.ActionArgs) {
  const { email, password, saveSession } = await zx.parseForm(request, {
    email: z.string().email(),
    password: z.string().min(6),
    saveSession: zx.CheckboxAsString,
  })
}

与现有的Zod计划和模型/控制器相结合:

// db.ts
export const CreateNoteSchema = z.object({
  userId: z.string(),
  title: z.string(),
  category: NoteCategorySchema.optional(),
})

export function createNote(note: z.infer<typeof CreateNoteSchema>) {}
import { CreateNoteSchema, createNote } from './db'

export async function action({ request }: Route.ActionArgs) {
  const formData = await zx.parseForm(request, CreateNoteSchema)
  createNote(formData) // No TypeScript errors here
}

zx.parse查询(请求:请求,计划:Schema)

分析并验证 a 的查询字符串( 搜索参数) Request数字 :

export async function loader({ request }: Route.LoaderArgs) {
  const { count, page } = zx.parseQuery(request, {
    // NumAsString parses a string number ("5") and returns a number (5)
    count: zx.NumAsString,
    page: zx.NumAsString,
  })
}

zx.parseParamsSafe () / zx.parseFormSafe () / zx.parseQuerySafe ()

这些功能与非安全版本相同,但当验证失败时不要抛出. 他们用 z.parseSafe() ,并总是返回带有解析数据或错误的对象.

export async function action(args: Route.ActionArgs) {
  const results = await zx.parseFormSafe(args.request, {
    email: z.string().email({ message: 'Invalid email' }),
    password: z
      .string()
      .min(8, { message: 'Password must be at least 8 characters' }),
  })
  return {
    success: results.success,
    error: results.error,
  }
}

检查 登录页面示例 一个完整的例子.

处理错误

parseParams(), (中文(简体) ), parseForm(),以及 parseQuery()

当解析失败时, 这些函数会丢出一个 400 个响应 。 这件不错 反应路由器出错边界 并应该用于解析很少会失败并且不需要自定义错误处理的东西. 您可以通过自定义错误消息或状态代码.

export async function loader({ params }: Route.LoaderArgs) {
  const { postId } = zx.parseParams(
    params,
    { postId: zx.NumAsString },
    { message: "Invalid postId parameter", status: 400 }
  );
  const post = await getPost(postId);
  return { post };
}
export function ErrorBoundary() {
  const error = useRouteError();
  return <h1>Error: {error.statusText}</h1>;
}

检查 页面示例 一个完整的例子.

parseParamsSafe(), (中文(简体) ), parseFormSafe(),以及 parseQuerySafe()

这些功能对于形式验证是巨大的,因为它们在解析失败时不会抛出. 它们总是以这样的形状返回一个物体:

{ success: boolean; error?: ZodError; data?: <parsed data>; }

然后可以处理动作中的错误,并在组件中使用 useActionData()。检查 登录页面示例 一个完整的例子.

动态图

有时需要根据运行时间数据(如从数据库中过滤选项)动态地构建计划. Zodix为这种模式提供了出色的支持.

类型推论帮助器

使用 InferParams 从您的策略中获取明确类型的类型:

import { zx, type InferParams } from '@coji/zodix'

const mySchema = z.object({
  q: z.string().optional(),
  page: zx.IntAsString.optional(),
})

type Params = InferParams<typeof mySchema>
// → { q: string | undefined, page: number | undefined }

以 z.obobject (. extend () 构建动态形状

建议采用的动态计划办法 z.object().extend()数字 :

export async function loader({ request }: Route.LoaderArgs) {
  // Fetch dynamic filter categories from database/API
  const filterCategories = await getAvailableFilterCategories()
  // → [{ id: 'category', ... }, { id: 'brand', ... }, ...]

  // 1. Define base schema with known fields
  const baseSchema = z.object({
    q: z.string().optional(),
    page: zx.IntAsString.optional(),
  })

  // 2. Build dynamic fields from runtime data
  const dynamicFields = Object.fromEntries(
    filterCategories.map((cat) => [cat.id, z.string().optional()]),
  )

  // 3. Extend base schema with dynamic fields
  const fullSchema = baseSchema.extend(dynamicFields)

  // 4. Parse with full type inference (Zod v4)
  const parsed = zx.parseQuery(request, fullSchema)
  // ✨ parsed.q is string | undefined
  // ✨ parsed.page is number | undefined
  // ✨ parsed[category.id] is string | undefined
}

说明: 使用 Zod v3, 动态字段的类型推论可能返回 any 由于TypeScript的限制. 为了与v3进行更好的类型安全,考虑其他方法.

备选办法

关于更先进的使用案例和替代模式(URLSearchParams、JSON记录等),见 动态 Schemas 指南本指南涵盖:

  • 三种不同的取舍办法
  • Zod v3 vs v4 考虑因素
  • 实际世界实例(电子商务过滤器、管理仪表板、多租户SaaS)
  • 集中式计划定义的最佳做法

检查 动态过滤器示例 (c) 全面开展工作.

援助者 Zod Schemas

因为 FormData 财务报告和审定财务报表 URLSearchParams 将所有值序列化为字符串,你往往会遇到诸如 "5", (中文(简体) ), "on" 财务报告和审定财务报表 "true"。帮助者 schemas 处理解析和验证代表其他数据类型的字符串,并打算与解析函数一起使用.

可用的助手

zx. BoolAsstring (英语)

  • "true" → true
  • "false" → false
  • "notboolean" 掷出 ZodError

zx. 检查框

  • "on" → true
  • undefined → false
  • "anythingbuton" 掷出 ZodError

z. 插入结构

  • "3" → 3
  • "3.14" 掷出 ZodError
  • "notanumber" 掷出 ZodError

z. 数字结构

  • "3" → 3
  • "3.14" → 3.14
  • "notanumber" 掷出 ZodError

见 测试 更多细节.

使用量

const Schema = z.object({
  isAdmin: zx.BoolAsString,
  agreedToTerms: zx.CheckboxAsString,
  age: zx.IntAsString,
  cost: zx.NumAsString,
})

const parsed = Schema.parse({
  isAdmin: 'true',
  agreedToTerms: 'on',
  age: '38',
  cost: '10.99',
})

/*
parsed = {
  isAdmin: true,
  agreedToTerms: true,
  age: 38,
  cost: 10.99
}
*/

Zod v3/v4 兼容性细节

如何运作

Zodix为 Zod v3 和 v4 兼容性提供了单独的导入路径 :

  1. 使用适当的导入路径 基于您的 Zod 版本
  2. 全类型安全 两个版本都保留
  3. 相同的 API 跨越两个版本 - 只有导入路径更改

与 Zod v3 使用

import { z } from 'zod' // v3.x
import { zx } from '@coji/zodix' // Default path for v3

const schema = z.object({
  name: z.string(),
  age: zx.IntAsString,
})

export async function loader({ params }: Route.LoaderArgs) {
  const data = zx.parseParams(params, schema) // Works with Zod v3!
}

与 Zod v4 使用

import { z } from 'zod' // v4.x
import { zx } from '@coji/zodix/v4' // Use v4 path

const schema = z.object({
  name: z.string(),
  age: zx.IntAsString,
})

export async function loader({ params }: Route.LoaderArgs) {
  const data = zx.parseParams(params, schema) // Works with Zod v4!
}

额外

自定义 URLSearchParams 解析

您可能有包含查询字符串的 URL, 看上去像 ?ids[]=1&ids[]=2 或者说 ?ids=1,2 里面的建筑没有像现在这样 URLSearchParams 解析.

您可以通过自定义函数, 或者使用库 查询字符串 用Zodix来分析它们.

// Create a custom parser function
type ParserFunction = (
  params: URLSearchParams,
) => Record<string, string | string[]>
const customParser: ParserFunction = () => {
  /* ... */
}

// Parse non-standard search params
const search = new URLSearchParams(`?ids[]=id1&ids[]=id2`)
const { ids } = zx.parseQuery(
  request,
  { ids: z.array(z.string()) },
  { parser: customParser },
)

// ids = ['id1', 'id2']

有多重意图的行动

Zod受歧视的工会在帮助处理这种多重意图的行动方面表现得很好:

// This adds type narrowing by the intent property
const Schema = z.discriminatedUnion('intent', [
  z.object({ intent: z.literal('delete'), id: z.string() }),
  z.object({ intent: z.literal('create'), name: z.string() }),
])

export async function action({ request }: Route.ActionArgs) {
  const data = await zx.parseForm(request, Schema)
  switch (data.intent) {
    case 'delete':
      // data is now narrowed to { intent: 'delete', id: string }
      return { success: true }
    case 'create':
      // data is now narrowed to { intent: 'create', name: string }
      return { success: true }
    default:
      // data is now narrowed to never. This will error if a case is missing.
      const _exhaustiveCheck: never = data
  }
}

承认

这个项目是一个叉子 里托马塞克/佐迪克斯感谢Riley Tomasek创建了最初的Zodix图书馆.

版本与发布记录

@coji/zodix 共发布 3 个版本,首次发布于 2025/08/07;过去 12 个月发布了 0 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
0.7.0latest2025/11/011 年前
0.6.22025/11/011 年前
0.5.02025/08/071.3 年前

关于 @coji/zodix 的常见问题

@coji/zodix 是什么?

与 Zod 解析回放路由器加载器和动作

如何安装 @coji/zodix?

在项目目录运行 npm install @coji/zodix,或使用 pnpm add / yarn add / bun add。

@coji/zodix 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@coji/zodix 支持 ESM 还是 CommonJS?

同时提供 ES Module 与 CommonJS 入口,import 和 require() 都可以使用,打包工具会自动选择合适的版本。

@coji/zodix 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=22。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@coji/zodix 可以商用吗?

@coji/zodix 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@coji/zodix 的下载量有多少?

根据 npm 官方下载统计,@coji/zodix 在 2026/10/11 – 2026/11/09 这 30 天内被下载 2,292 次,日均约 76 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@coji/zodix 还在维护吗?

最新版本 0.7.0 发布于 2025/11/01(1 年前);至今共发布 3 个版本,其中过去 12 个月发布了 0 个;首次发布于 2025/08/07。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。