An open API service indexing awesome lists of open source software.

https://github.com/felipstein/zod-hookform-union-helper

TypeScript helper library to seamlessly integrate zod discriminated unions with react-hook-form, resolving common type issues.
https://github.com/felipstein/zod-hookform-union-helper

form-validation typescript typescript-union-errors union-type-errors union-type-validation zod zod-discriminated-uinon-type zod-union-issue

Last synced: 10 months ago
JSON representation

TypeScript helper library to seamlessly integrate zod discriminated unions with react-hook-form, resolving common type issues.

Awesome Lists containing this project

README

          

# `zod-hookform-union-helper`

## Introduction

Developers frequently face challenges when integrating `zod` with `react-hook-form`, particularly when working with discriminated unions.

## The Issue

When using discriminated unions with `zod` and `react-hook-form`, TypeScript often throws type errors that can be confusing. For instance:

Given a union type in `zod`:

```typescript
const FormCertificateSchemaCertificate = z.discriminatedUnion("certificate", [ ... ]);
```

And when integrating it with `react-hook-form`:

```tsx
{watch('certificate') === 'birth' && (

)}
```

TypeScript flags an error at `errors.birth?.message`, indicating that `birth` doesn't exist within `errors`. Technically, this is true until `certificate` is set to `birth`. This means even if your component's logic correctly recognizes the `birth` field once `certificate` is set, TypeScript doesn't acknowledge this initially, leading to unnecessary type errors.

## The Solution: `zod-hookform-union-helper`

The `zod-hookform-union-helper` library leverages TypeScript capabilities to consolidate fragmented error unions into one cohesive type.

### Installation:

```bash
npm install zod-hookform-union-helper
```

### Usage:

There are two primary ways to implement `zod-hookform-union-helper`:

#### 1. Using the `unifyErrors` function:

```tsx
import { useForm } from 'react-hook-form'
import { zodResolver } from '@hookform/resolvers/zod'
import { unifyErrors } from 'zod-hookform-union-helper'

// ...

const {
formState: { errors },
} = useForm()

const errorsUnified = unifyErrors(errors) // use errorsUnified in your component
```

#### 2. Using TypeScript type casting:

```tsx
import { useForm } from 'react-hook-form'
import { zodResolver } from '@hookform/resolvers/zod'

import type { UnifiedErrors } from 'zod-hookform-union-helper'

// ...

const {
formState: { errors },
} = useForm()

const errorsUnified = errors as UnifiedErrors // use errorsUnified in your component
```

## Examples

Revisiting the scenario described in the "The Issue" section:

Without using `zod-hookform-union-helper`:
```tsx
{watch('certificate') === 'birth' && (

)}
```
With this setup, TypeScript throws a type error at `errors.birth?.message`.

Now, employing `zod-hookform-union-helper`:
```tsx
const errorsUnified = unifyErrors(errors);

{watch('certificate') === 'birth' && (

)}
```
In this instance, TypeScript acknowledges `errorsUnified.birth?.message` without any issue.

## Requirements

- TypeScript version 3.0 or higher.

## Contributing

Feedback and contributions are welcome! Please open an issue or submit a PR if you have suggestions, improvements, or bug fixes.