Skip to content

Commit

Permalink
fix(Yup resolver): schema type error (#563)
Browse files Browse the repository at this point in the history
* Fix schema type error mentioned in issue #549 

* Improves yup type inference

Improves yup type inference to make generic casting for useForm unnecessary
  • Loading branch information
henrikvolmer authored Jun 12, 2023
1 parent d2d6fec commit 420e862
Show file tree
Hide file tree
Showing 5 changed files with 31 additions and 37 deletions.
8 changes: 4 additions & 4 deletions yup/src/__tests__/Form.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from 'react';
import { render, screen } from '@testing-library/react';
import user from '@testing-library/user-event';
import { useForm } from 'react-hook-form';
import { SubmitHandler, useForm } from 'react-hook-form';
import * as Yup from 'yup';
import { yupResolver } from '..';

Expand All @@ -10,18 +10,18 @@ const schema = Yup.object({
password: Yup.string().required(),
});

type FormData = Yup.InferType<typeof schema> & { unusedProperty: string };
type FormData = Yup.InferType<typeof schema>;

interface Props {
onSubmit: (data: FormData) => void;
onSubmit: SubmitHandler<FormData>;
}

function TestComponent({ onSubmit }: Props) {
const {
register,
formState: { errors },
handleSubmit,
} = useForm<FormData>({
} = useForm({
resolver: yupResolver(schema), // Useful to check TypeScript regressions
});

Expand Down
7 changes: 4 additions & 3 deletions yup/src/__tests__/__fixtures__/data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export const schemaWithWhen = yup.object({
}),
});

export const validData: yup.InferType<typeof schema> = {
export const validData = {
username: 'Doe',
password: 'Password123_',
repeatPassword: 'Password123_',
Expand All @@ -50,14 +50,15 @@ export const validData: yup.InferType<typeof schema> = {
name: 'name',
},
],
};
} satisfies yup.InferType<typeof schema>;

export const invalidData = {
password: '___',
email: '',
birthYear: 'birthYear',
like: [{ id: 'z' }],
};
// Must be set to "unknown", otherwise typescript knows that it is invalid
} as unknown as Required<yup.InferType<typeof schema>>;

export const fields: Record<InternalFieldName, Field['_f']> = {
username: {
Expand Down
1 change: 0 additions & 1 deletion yup/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
export * from './yup';
export * from './types';
24 changes: 0 additions & 24 deletions yup/src/types.ts

This file was deleted.

28 changes: 23 additions & 5 deletions yup/src/yup.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import * as Yup from 'yup';
import { toNestError, validateFieldsNatively } from '@hookform/resolvers';
import { appendErrors, FieldError } from 'react-hook-form';
import { Resolver } from './types';
import {
appendErrors,
FieldError,
FieldValues,
Resolver,
} from 'react-hook-form';

/**
* Why `path!` ? because it could be `undefined` in some case
Expand Down Expand Up @@ -38,9 +42,22 @@ const parseErrorSchema = (
);
};

export const yupResolver: Resolver =
(schema, schemaOptions = {}, resolverOptions = {}) =>
async (values, context, options) => {
export function yupResolver<TFieldValues extends FieldValues>(
schema: Yup.ObjectSchema<TFieldValues>,
schemaOptions: Parameters<(typeof schema)['validate']>[1] = {},
resolverOptions: {
/**
* @default async
*/
mode?: 'async' | 'sync';
/**
* Return the raw input values rather than the parsed values.
* @default false
*/
raw?: boolean;
} = {},
): Resolver<TFieldValues> {
return async (values, context, options) => {
try {
if (schemaOptions.context && process.env.NODE_ENV === 'development') {
// eslint-disable-next-line no-console
Expand Down Expand Up @@ -80,3 +97,4 @@ export const yupResolver: Resolver =
};
}
};
}

0 comments on commit 420e862

Please sign in to comment.