TanStackT
TanStack2mo ago
15 replies
popular-magenta

more laxist input types while keeping tight output types

I implemented a wrapper around the useForm param to avoid having to pass the whole defaultValues data structure when creating a form (which honestly is quite cumbersome when all values are undefined by default). i had to combine the types of the input schema and default values in order to stitch back the form types to make tsc happy. here's the function:

export function formConfig<Schema extends z.ZodObject, Defaults extends object>({
  defaultValues,
  schema,
  onSubmit,
}: {
  defaultValues?: Defaults
  schema: Schema
  onSubmit: (props: { value: z.output<Schema> & Defaults }) => void
}) {
  return {
    defaultValues: defaultValues as z.input<Schema> & Defaults,
    validators: {
      onSubmit: ({ value }) => {
        const result = schema.safeParse({
          ...defaultValues,
          ...value,
        })

        return result.success ? undefined : result.error
      },
    },
    onSubmit,
    onSubmitInvalid: (args) => console.log(args),
  }
}


used as:

const form = useForm(
  formConfig({
    defaultValues: {}, // becomes optional and can be partial,
    schema: someZodSchema,
    onSubmit({ value }) => {}, // value is union of defaultValues and z.output<schema>
  })
)


it does work well to one exception: i wished to add that the type representing the form's values (i guess, typeof defaultValues) would be wrapped Partial to support the pristine and reset states of the inputs from types PoV. When i change:

- defaultValues: defaultValues as z.input<Schema> & Defaults,
+ defaultValues: defaultValues as Partial<z.input<Schema>> & Defaults,


i get a type mismatch Types of property 'defaultValues' are incompatible.. I'm a bit lost at this error because i only declare (and cast) the defaultValues so the comparison with another defaultValues might not come from me.

1. Is there a way to decouple the form values defaultValues from the rest of the lib
2. Or is there another way to achieve what i want to do?
Was this page helpful?