Added AI skills
This commit is contained in:
131
.agents/skills/zod/references/error-use-flatten.md
Normal file
131
.agents/skills/zod/references/error-use-flatten.md
Normal file
@@ -0,0 +1,131 @@
|
||||
---
|
||||
title: Use flatten() for Form Error Display
|
||||
impact: HIGH
|
||||
impactDescription: Raw ZodError.issues requires manual path parsing; flatten() provides field-keyed errors ready for form display
|
||||
tags: error, flatten, forms, user-experience
|
||||
---
|
||||
|
||||
## Use flatten() for Form Error Display
|
||||
|
||||
`ZodError.issues` is an array that requires manual processing to map errors to form fields. `ZodError.flatten()` returns an object with `fieldErrors` keyed by field name, ready for form libraries and UI display.
|
||||
|
||||
**Incorrect (manual issue processing):**
|
||||
|
||||
```typescript
|
||||
import { z } from 'zod'
|
||||
|
||||
const formSchema = z.object({
|
||||
email: z.string().email('Invalid email'),
|
||||
password: z.string().min(8, 'Password too short'),
|
||||
profile: z.object({
|
||||
name: z.string().min(1, 'Name required'),
|
||||
}),
|
||||
})
|
||||
|
||||
function getFieldErrors(error: z.ZodError) {
|
||||
const errors: Record<string, string> = {}
|
||||
|
||||
for (const issue of error.issues) {
|
||||
// Manual path joining - error prone
|
||||
const field = issue.path.join('.')
|
||||
if (!errors[field]) {
|
||||
errors[field] = issue.message
|
||||
}
|
||||
}
|
||||
|
||||
return errors
|
||||
}
|
||||
|
||||
const result = formSchema.safeParse(data)
|
||||
if (!result.success) {
|
||||
const errors = getFieldErrors(result.error)
|
||||
// { email: 'Invalid email', 'profile.name': 'Name required' }
|
||||
}
|
||||
```
|
||||
|
||||
**Correct (using flatten):**
|
||||
|
||||
```typescript
|
||||
import { z } from 'zod'
|
||||
|
||||
const formSchema = z.object({
|
||||
email: z.string().email('Invalid email'),
|
||||
password: z.string().min(8, 'Password too short'),
|
||||
profile: z.object({
|
||||
name: z.string().min(1, 'Name required'),
|
||||
}),
|
||||
})
|
||||
|
||||
const result = formSchema.safeParse(data)
|
||||
|
||||
if (!result.success) {
|
||||
const { formErrors, fieldErrors } = result.error.flatten()
|
||||
|
||||
// formErrors: string[] - top-level errors (from .refine on the object)
|
||||
// fieldErrors: { [key]: string[] } - errors by field
|
||||
|
||||
// Ready for form display
|
||||
console.log(fieldErrors)
|
||||
// {
|
||||
// email: ['Invalid email'],
|
||||
// password: ['Password too short'],
|
||||
// 'profile.name': ['Name required']
|
||||
// }
|
||||
}
|
||||
```
|
||||
|
||||
**With React Hook Form:**
|
||||
|
||||
```typescript
|
||||
import { zodResolver } from '@hookform/resolvers/zod'
|
||||
import { useForm } from 'react-hook-form'
|
||||
|
||||
const { register, formState: { errors } } = useForm({
|
||||
resolver: zodResolver(formSchema),
|
||||
})
|
||||
|
||||
// errors are already flattened by the resolver
|
||||
// <input {...register('email')} />
|
||||
// {errors.email && <span>{errors.email.message}</span>}
|
||||
```
|
||||
|
||||
**Customizing flatten output:**
|
||||
|
||||
```typescript
|
||||
const flattened = result.error.flatten((issue) => ({
|
||||
message: issue.message,
|
||||
code: issue.code,
|
||||
}))
|
||||
|
||||
// fieldErrors now contains custom objects
|
||||
// {
|
||||
// email: [{ message: 'Invalid email', code: 'invalid_string' }],
|
||||
// }
|
||||
```
|
||||
|
||||
**For deeply nested objects, use format():**
|
||||
|
||||
```typescript
|
||||
const result = formSchema.safeParse(data)
|
||||
|
||||
if (!result.success) {
|
||||
const formatted = result.error.format()
|
||||
// {
|
||||
// _errors: [],
|
||||
// email: { _errors: ['Invalid email'] },
|
||||
// profile: {
|
||||
// _errors: [],
|
||||
// name: { _errors: ['Name required'] }
|
||||
// }
|
||||
// }
|
||||
|
||||
// Access nested errors naturally
|
||||
formatted.profile?.name?._errors // ['Name required']
|
||||
}
|
||||
```
|
||||
|
||||
**When NOT to use this pattern:**
|
||||
- When you need access to full issue metadata (code, path as array)
|
||||
- When using a form library that expects different error format
|
||||
|
||||
Reference: [Zod Error Handling](https://zod.dev/error-handling)
|
||||
Reference in New Issue
Block a user