Skip to content

Commit c0fdb95

Browse files
committed
feat(computed-types): type inference
1 parent 157d110 commit c0fdb95

File tree

2 files changed

+61
-5
lines changed

2 files changed

+61
-5
lines changed

computed-types/src/__tests__/computed-types.ts

+55-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1+
import { Resolver, SubmitHandler, useForm } from 'react-hook-form';
12
import { computedTypesResolver } from '..';
23
import { fields, invalidData, schema, validData } from './__fixtures__/data';
4+
import Schema, { number } from 'computed-types';
35

46
const shouldUseNativeValidation = false;
57

@@ -28,7 +30,6 @@ describe('computedTypesResolver', () => {
2830
});
2931

3032
const promise = computedTypesResolver(schemaWithCustomError)(
31-
// @ts-expect-error expect to throw
3233
validData,
3334
undefined,
3435
{
@@ -39,4 +40,57 @@ describe('computedTypesResolver', () => {
3940

4041
await expect(promise).rejects.toThrow('custom error');
4142
});
43+
44+
/**
45+
* Type inference tests
46+
*/
47+
it('should correctly infer the output type from a computedTypes schema', () => {
48+
const resolver = computedTypesResolver(Schema({ id: number }));
49+
50+
expectTypeOf(resolver).toEqualTypeOf<
51+
Resolver<{ id: number }, unknown, { id: number }>
52+
>();
53+
});
54+
55+
it('should correctly infer the output type from a computedTypes schema using a transform', () => {
56+
const resolver = computedTypesResolver(
57+
Schema({ id: number.transform((val) => String(val)) }),
58+
);
59+
60+
expectTypeOf(resolver).toEqualTypeOf<
61+
Resolver<{ id: number }, unknown, { id: string }>
62+
>();
63+
});
64+
65+
it('should correctly infer the output type from a computedTypes schema for the handleSubmit function in useForm', () => {
66+
const schema = Schema({ id: number });
67+
68+
const form = useForm({
69+
resolver: computedTypesResolver(schema),
70+
});
71+
72+
expectTypeOf(form.watch('id')).toEqualTypeOf<number>();
73+
74+
expectTypeOf(form.handleSubmit).parameter(0).toEqualTypeOf<
75+
SubmitHandler<{
76+
id: number;
77+
}>
78+
>();
79+
});
80+
81+
it('should correctly infer the output type from a computedTypes schema with a transform for the handleSubmit function in useForm', () => {
82+
const schema = Schema({ id: number.transform((val) => String(val)) });
83+
84+
const form = useForm({
85+
resolver: computedTypesResolver(schema),
86+
});
87+
88+
expectTypeOf(form.watch('id')).toEqualTypeOf<number>();
89+
90+
expectTypeOf(form.handleSubmit).parameter(0).toEqualTypeOf<
91+
SubmitHandler<{
92+
id: string;
93+
}>
94+
>();
95+
});
4296
});

computed-types/src/computed-types.ts

+6-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { toNestErrors, validateFieldsNatively } from '@hookform/resolvers';
22
import { Type, ValidationError } from 'computed-types';
33
import FunctionType from 'computed-types/lib/schema/FunctionType';
4-
import type { FieldErrors, Resolver } from 'react-hook-form';
4+
import type { FieldErrors, FieldValues, Resolver } from 'react-hook-form';
55

66
const isValidationError = (error: any): error is ValidationError =>
77
error.errors != null;
@@ -32,9 +32,11 @@ function parseErrorSchema(computedTypesError: ValidationError) {
3232
* resolver: computedTypesResolver(schema)
3333
* });
3434
*/
35-
export function computedTypesResolver<Schema extends FunctionType<any, any>>(
36-
schema: Schema,
37-
): Resolver<Type<typeof schema>> {
35+
export function computedTypesResolver<
36+
Input extends FieldValues,
37+
Context,
38+
Output,
39+
>(schema: FunctionType<Output, [Input]>): Resolver<Input, Context, Output> {
3840
return async (values, _, options) => {
3941
try {
4042
const data = await schema(values);

0 commit comments

Comments
 (0)