zod_utilz 中文文档教程

发布于 2年前 浏览 16 项目主页 更新于 2年前

Zod Utilz 徽标

佐德·乌提兹

与框架无关的实用程序 佐德


目录

目的

  • 简化Zod
  • 填补 Zod 中可能缺少的功能空白>
  • Zod 中提供潜在新功能的实现

贡献

始终对想法持开放态度。无论是积极的还是消极的,都欢迎。欢迎贡献问题公关

另一个库

您可能不想安装另一个库只是为了访问您需要的Util。不用担心。请随意将您需要的代码复制并粘贴到您的项目中。当这个库更新时它不会更新,但它会减少你的包大小。 :D

也许将来会有一种方法可以只安装您需要的 Utilz。如果您知道如何执行此操作,请告诉我

安装

从 npm (Node/Bun)

npm install zod_utilz
yarn add zod_utilz
pnpm add zod_utilz
bun add zod_utilz

入门

import

Node/Bun

import { zu } from 'zod_utilz'

Deno

import { zu } from 'https://deno.land/x/zod_utilz/mod.ts'
// or
import { zu } from 'npm:zod_utilz'

Utilz

SPR

SPR 代表 SafeParseResult

这启用了 可选链接空值合并 z.SafeParseReturnType

import { zu } from 'zod_utilz'
const schema = z.object( { foo: z.string() } )
const result = zu.SPR( schema.safeParse( { foo: 42 } ) )
const fooDataOrErrors = result.data?.foo ?? result.error?.format().foo?._errors

makeErrorMap

简化制作 ZodErrorMap 的过程

import { zu } from 'zod_utilz'

const errorMap = zu.makeErrorMap( {
    required: 'Custom required message',
    invalid_type: ( { data } ) => `${ data } is an invalid type`,
    too_big: ( { maximum } ) => `Maximum length is ${ maximum }`,
    invalid_enum_value: ( { data, options } ) =>
        `${ data } is not a valid enum value. Valid options: ${ options?.join( ' | ' ) } `,
} )

const stringSchema = z.string( { errorMap } ).max( 32 )

zu.SPR( stringSchema.safeParse( undefined ) ).error?.issues[ 0 ].message
// Custom required message

zu.SPR( stringSchema.safeParse( 42 ) ).error?.issues[ 0 ].message
// 42 is an invalid type

zu.SPR( stringSchema.safeParse( 'this string is over the maximum length' ) ).error?.issues[ 0 ].message
// Maximum length is 32

const enumSchema = z.enum( [ 'foo', 'bar' ], { errorMap } )

zu.SPR( enumSchema.safeParse( 'baz' ) ).error?.issues[ 0 ].message
// baz is not a valid enum value. Valid options: foo | bar

useTypedParsers

启用 zod 解析器的编译时类型检查。

import { zu } from 'zod_utilz'
const schemaWithTypedParsers = zu.useTypedParsers( z.literal( 'foo' ) )

schemaWithTypedParsers.parse( 'foo' )
// no ts errors

schemaWithTypedParsers.parse( 'bar' )
//                            ^^^^^
// Argument of type '"bar"' is not assignable to parameter of type '"foo"'

coerce

强制将错误视为正常的 zod 错误。防止使用 safeParse 时抛出错误。

z.bigint()

import { zu } from 'zod_utilz'
const bigintSchema = zu.coerce( z.bigint() )
bigintSchema.parse( '42' ) // 42n
bigintSchema.parse( '42n' ) // 42n
zu.SPR( bigintSchema.safeParse( 'foo' ) ).error?.issues[ 0 ].message
// 'Expected bigint, received string'

z.boolean()

import { zu } from 'zod_utilz'
const booleanSchema = zu.coerce( z.boolean() )

// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean
// only exception to normal boolean coercion rules
booleanSchema.parse( 'false' ) // false

// https://developer.mozilla.org/en-US/docs/Glossary/Falsy
// falsy => false
booleanSchema.parse( false ) // false
booleanSchema.parse( 0 ) // false
booleanSchema.parse( -0 ) // false
booleanSchema.parse( 0n ) // false
booleanSchema.parse( '' ) // false
booleanSchema.parse( null ) // false
booleanSchema.parse( undefined ) // false
booleanSchema.parse( NaN ) // false

// truthy => true
booleanSchema.parse( 'foo' ) // true
booleanSchema.parse( 42 ) // true
booleanSchema.parse( [] ) // true
booleanSchema.parse( {} ) // true

z.number().array()

import { zu } from 'zod_utilz'
const numberArraySchema = zu.coerce( z.number().array() )

// if the value is not an array, it is coerced to an array with one coerced item
numberArraySchema.parse( 42 ) // [ 42 ]
numberArraySchema.parse( '42' ) // [ 42 ]

// if the value is an array, it coerces each item in the array
numberArraySchema.parse( [] ) // []
numberArraySchema.parse( [ '42', 42 ] ) // [ 42, 42 ]

zu.SPR( numberArraySchema.safeParse( 'foo' ) ).error?.issues[ 0 ].message
// 'Expected number, received nan'

useURLSearchParams

一种解析 URLSearchParams 的方法

import { zu } from 'zod_utilz'
const schema = zu.useURLSearchParams(
    z.object( {
        string: z.string(),
        number: z.number(),
        boolean: z.boolean(),
    } )
)

zu.SPR( schema.safeParse(
    new URLSearchParams( {
        string: 'foo',
        number: '42',
        boolean: 'false',
    } )
) ).data
// { string: 'foo', number: 42, boolean: false }

zu.SPR( schema.safeParse(
    new URLSearchParams( {
        string: '42',
        number: 'false',
        boolean: 'foo',
    } )
) ).error?.flatten().fieldErrors
// {
//     string: [ 'Expected string, received number' ],
//     number: [ 'Expected number, received boolean' ],
//     boolean: [ 'Expected boolean, received string' ],
// }

useFormData

一种解析 FormData 的方法

import { zu } from 'zod_utilz'
const schema = zu.useFormData(
    z.object( {
        string: z.string(),
        number: z.number(),
        boolean: z.boolean(),
        file: z.instanceof( File ),
    } )
)
const formData = new FormData()
formData.append( 'string', 'foo' )
formData.append( 'number', '42' )
formData.append( 'boolean', 'false' )
formData.append( 'file', new File( [], 'filename.ext' ) )

zu.SPR( schema.safeParse( formData ) ).data,
// { string: 'foo', number: 42, boolean: false, file: File }
const formData = new FormData()
formData.append( 'string', '42' )
formData.append( 'number', 'false' )
formData.append( 'boolean', 'foo' )
formData.append( 'file', 'filename.ext' )

zu.SPR( schema.safeParse( formData ) ).error?.flatten().fieldErrors,
// {
//     string: [ 'Expected string, received number' ],
//     number: [ 'Expected number, received boolean' ],
//     boolean: [ 'Expected boolean, received string' ],
//     file: [ 'Input not instance of File' ],
// }

partialSafeParsepartialSafeParse

允许您获取有效字段,即使另一个字段中存在错误

import { zu } from 'zod_utilz'
const userSchema = z.object( { name: z.string(), age: z.number() } )
const result = zu.partialSafeParse( userSchema, { name: null, age: 42 } )
// {
//     successType: 'partial',
//     validData: { age: 42 },
//     invalidData: { name: null },
// }
result.error?.flatten().fieldErrors
// {
//     name: [ 'Expected string, received null' ],
// }

TODO

始终对想法持开放态度。无论是积极的还是消极的,都欢迎。欢迎贡献问题公关

  • zu.coerce
    • z.date()
    • z.object()
      • 递归强制 props
      • https://github.com/colinhacks/zod/discussions/1910
  • enum pick/omit
    • https://github.com/colinhacks/zod/discussions/1922
  • BaseType(递归获取a的基本类型Zod 类型)
  • zu.baseType( z.string() ) => z.string()
  • zu.baseType( z.string().可选() ) => z.string()
  • zu.baseType( z.string().可选().refine() ) => z.string()
  • zu.baseType( z.string().array().可选().refine() ) => z.string().array()
  • 制作缩小
  • GitHub Actions
      的过程
    • 自动发布到 npm
Zod Utilz logo

Zod Utilz

Framework agnostic utilities for Zod


Table of contents

Purpose

  • Simplify common tasks in Zod
  • Fill the gap of features that might be missing in Zod
  • Provide implementations for potential new features in Zod

Contribute

Always open to ideas. Positive or negative, all are welcome. Feel free to contribute an issue or PR.

Yet another library

You might not want to install yet another library only to get access to that one Util you need. No worries. Feel free to copy and paste the code you need into your project. It won't get updated when this library gets updated, but it will reduce your bundle size. :D

Perhaps in the future there will be a way to install only the Utilz you need. If you know how to do this, please let me know.

Installation

From npm (Node/Bun)

npm install zod_utilz
yarn add zod_utilz
pnpm add zod_utilz
bun add zod_utilz

Getting Started

import

Node/Bun

import { zu } from 'zod_utilz'

Deno

import { zu } from 'https://deno.land/x/zod_utilz/mod.ts'
// or
import { zu } from 'npm:zod_utilz'

Utilz

SPR

SPR stands for SafeParseResult

This enables optional chaining or nullish coalescing for z.SafeParseReturnType.

import { zu } from 'zod_utilz'
const schema = z.object( { foo: z.string() } )
const result = zu.SPR( schema.safeParse( { foo: 42 } ) )
const fooDataOrErrors = result.data?.foo ?? result.error?.format().foo?._errors

makeErrorMap

Simplifies the process of making a ZodErrorMap

import { zu } from 'zod_utilz'

const errorMap = zu.makeErrorMap( {
    required: 'Custom required message',
    invalid_type: ( { data } ) => `${ data } is an invalid type`,
    too_big: ( { maximum } ) => `Maximum length is ${ maximum }`,
    invalid_enum_value: ( { data, options } ) =>
        `${ data } is not a valid enum value. Valid options: ${ options?.join( ' | ' ) } `,
} )

const stringSchema = z.string( { errorMap } ).max( 32 )

zu.SPR( stringSchema.safeParse( undefined ) ).error?.issues[ 0 ].message
// Custom required message

zu.SPR( stringSchema.safeParse( 42 ) ).error?.issues[ 0 ].message
// 42 is an invalid type

zu.SPR( stringSchema.safeParse( 'this string is over the maximum length' ) ).error?.issues[ 0 ].message
// Maximum length is 32

const enumSchema = z.enum( [ 'foo', 'bar' ], { errorMap } )

zu.SPR( enumSchema.safeParse( 'baz' ) ).error?.issues[ 0 ].message
// baz is not a valid enum value. Valid options: foo | bar

useTypedParsers

Enables compile time type checking for zod parsers.

import { zu } from 'zod_utilz'
const schemaWithTypedParsers = zu.useTypedParsers( z.literal( 'foo' ) )

schemaWithTypedParsers.parse( 'foo' )
// no ts errors

schemaWithTypedParsers.parse( 'bar' )
//                            ^^^^^
// Argument of type '"bar"' is not assignable to parameter of type '"foo"'

coerce

Coercion that treats errors like normal zod errors. Prevents throwing errors when using safeParse.

z.bigint()

import { zu } from 'zod_utilz'
const bigintSchema = zu.coerce( z.bigint() )
bigintSchema.parse( '42' ) // 42n
bigintSchema.parse( '42n' ) // 42n
zu.SPR( bigintSchema.safeParse( 'foo' ) ).error?.issues[ 0 ].message
// 'Expected bigint, received string'

z.boolean()

import { zu } from 'zod_utilz'
const booleanSchema = zu.coerce( z.boolean() )

// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean
// only exception to normal boolean coercion rules
booleanSchema.parse( 'false' ) // false

// https://developer.mozilla.org/en-US/docs/Glossary/Falsy
// falsy => false
booleanSchema.parse( false ) // false
booleanSchema.parse( 0 ) // false
booleanSchema.parse( -0 ) // false
booleanSchema.parse( 0n ) // false
booleanSchema.parse( '' ) // false
booleanSchema.parse( null ) // false
booleanSchema.parse( undefined ) // false
booleanSchema.parse( NaN ) // false

// truthy => true
booleanSchema.parse( 'foo' ) // true
booleanSchema.parse( 42 ) // true
booleanSchema.parse( [] ) // true
booleanSchema.parse( {} ) // true

z.number().array()

import { zu } from 'zod_utilz'
const numberArraySchema = zu.coerce( z.number().array() )

// if the value is not an array, it is coerced to an array with one coerced item
numberArraySchema.parse( 42 ) // [ 42 ]
numberArraySchema.parse( '42' ) // [ 42 ]

// if the value is an array, it coerces each item in the array
numberArraySchema.parse( [] ) // []
numberArraySchema.parse( [ '42', 42 ] ) // [ 42, 42 ]

zu.SPR( numberArraySchema.safeParse( 'foo' ) ).error?.issues[ 0 ].message
// 'Expected number, received nan'

useURLSearchParams

A way to parse URLSearchParams

import { zu } from 'zod_utilz'
const schema = zu.useURLSearchParams(
    z.object( {
        string: z.string(),
        number: z.number(),
        boolean: z.boolean(),
    } )
)

zu.SPR( schema.safeParse(
    new URLSearchParams( {
        string: 'foo',
        number: '42',
        boolean: 'false',
    } )
) ).data
// { string: 'foo', number: 42, boolean: false }

zu.SPR( schema.safeParse(
    new URLSearchParams( {
        string: '42',
        number: 'false',
        boolean: 'foo',
    } )
) ).error?.flatten().fieldErrors
// {
//     string: [ 'Expected string, received number' ],
//     number: [ 'Expected number, received boolean' ],
//     boolean: [ 'Expected boolean, received string' ],
// }

useFormData

A way to parse FormData

import { zu } from 'zod_utilz'
const schema = zu.useFormData(
    z.object( {
        string: z.string(),
        number: z.number(),
        boolean: z.boolean(),
        file: z.instanceof( File ),
    } )
)
const formData = new FormData()
formData.append( 'string', 'foo' )
formData.append( 'number', '42' )
formData.append( 'boolean', 'false' )
formData.append( 'file', new File( [], 'filename.ext' ) )

zu.SPR( schema.safeParse( formData ) ).data,
// { string: 'foo', number: 42, boolean: false, file: File }
const formData = new FormData()
formData.append( 'string', '42' )
formData.append( 'number', 'false' )
formData.append( 'boolean', 'foo' )
formData.append( 'file', 'filename.ext' )

zu.SPR( schema.safeParse( formData ) ).error?.flatten().fieldErrors,
// {
//     string: [ 'Expected string, received number' ],
//     number: [ 'Expected number, received boolean' ],
//     boolean: [ 'Expected boolean, received string' ],
//     file: [ 'Input not instance of File' ],
// }

partialSafeParse

partialSafeParse allows you to get the valid fields even if there was an error in another field

import { zu } from 'zod_utilz'
const userSchema = z.object( { name: z.string(), age: z.number() } )
const result = zu.partialSafeParse( userSchema, { name: null, age: 42 } )
// {
//     successType: 'partial',
//     validData: { age: 42 },
//     invalidData: { name: null },
// }
result.error?.flatten().fieldErrors
// {
//     name: [ 'Expected string, received null' ],
// }

TODO

Always open to ideas. Positive or negative, all are welcome. Feel free to contribute an issue or PR.

  • zu.coerce
    • z.date()
    • z.object()
      • recursively coerce props
      • https://github.com/colinhacks/zod/discussions/1910
  • enum pick/omit
    • https://github.com/colinhacks/zod/discussions/1922
  • BaseType (Recursively get the base type of a Zod type)
  • zu.baseType( z.string() ) => z.string()
  • zu.baseType( z.string().optional() ) => z.string()
  • zu.baseType( z.string().optional().refine() ) => z.string()
  • zu.baseType( z.string().array().optional().refine() ) => z.string().array()
  • Make process for minifying
  • GitHub Actions
    • Auto publish to npm
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文