Added AI skills

This commit is contained in:
Jose Selesan
2026-09-04 16:49:24 -03:00
parent 778f3fdcad
commit dfa7f73ebb
368 changed files with 51560 additions and 0 deletions

View 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)