From 411dd94a9264f31fd598c8ef5a85da8dcb0d2dd4 Mon Sep 17 00:00:00 2001 From: Sebastian Hoffmann Date: Tue, 11 Mar 2025 22:22:43 +0100 Subject: [PATCH] feat(types): make types on functions extend off the base classes generic instead of equal to them Basically, this fails: ```ts type Test = { defaultValues: T fun: (props: { value: T }) => {} } const t: Test<{ firstName: string }> = {} as Test<{ firstName: string, lastName: string }> ``` While this works: ```ts type Test2 = { defaultValues: T, fun: (props: { value: TF }) => void } // ist fine, the actual type has all that was asked for and then some const t2: Test2<{ firstName: string }> = {} as Test2<{ firstName: string, lastName: string }> ``` and still ensures that `firstName` is included on t2. The main idea is unless `props.value` only extends T, TypeScript checks the equality both ways. If it does extend T, the checking becomes unidirectional --- packages/form-core/src/FormApi.ts | 144 ++++++++++++++++-------------- 1 file changed, 79 insertions(+), 65 deletions(-) diff --git a/packages/form-core/src/FormApi.ts b/packages/form-core/src/FormApi.ts index e2640f8c9..fbef3eec5 100644 --- a/packages/form-core/src/FormApi.ts +++ b/packages/form-core/src/FormApi.ts @@ -193,40 +193,43 @@ export interface FormValidators< */ export interface FormTransform< TFormData, - TOnMount extends undefined | FormValidateOrFn, - TOnChange extends undefined | FormValidateOrFn, - TOnChangeAsync extends undefined | FormAsyncValidateOrFn, - TOnBlur extends undefined | FormValidateOrFn, - TOnBlurAsync extends undefined | FormAsyncValidateOrFn, - TOnSubmit extends undefined | FormValidateOrFn, - TOnSubmitAsync extends undefined | FormAsyncValidateOrFn, - TOnServer extends undefined | FormAsyncValidateOrFn, TSubmitMeta = never, > { - fn: ( + fn: < + TFFormData extends TFormData, + TFOnMount extends undefined | FormValidateOrFn, + TFOnChange extends undefined | FormValidateOrFn, + TFOnChangeAsync extends undefined | FormAsyncValidateOrFn, + TFOnBlur extends undefined | FormValidateOrFn, + TFOnBlurAsync extends undefined | FormAsyncValidateOrFn, + TFOnSubmit extends undefined | FormValidateOrFn, + TFOnSubmitAsync extends undefined | FormAsyncValidateOrFn, + TFOnServer extends undefined | FormValidateOrFn, + TFSubmitMeta extends TSubmitMeta + >( formBase: FormApi< - TFormData, - TOnMount, - TOnChange, - TOnChangeAsync, - TOnBlur, - TOnBlurAsync, - TOnSubmit, - TOnSubmitAsync, - TOnServer, - TSubmitMeta + TFFormData, + TFOnMount, + TFOnChange, + TFOnChangeAsync, + TFOnBlur, + TFOnBlurAsync, + TFOnSubmit, + TFOnSubmitAsync, + TFOnServer, + TFSubmitMeta >, ) => FormApi< - TFormData, - TOnMount, - TOnChange, - TOnChangeAsync, - TOnBlur, - TOnBlurAsync, - TOnSubmit, - TOnSubmitAsync, - TOnServer, - TSubmitMeta + TFFormData, + TFOnMount, + TFOnChange, + TFOnChangeAsync, + TFOnBlur, + TFOnBlurAsync, + TFOnSubmit, + TFOnSubmitAsync, + TFOnServer, + TFSubmitMeta > deps: unknown[] } @@ -296,52 +299,63 @@ export interface FormOptions< /** * A function to be called when the form is submitted, what should happen once the user submits a valid form returns `any` or a promise `Promise` */ - onSubmit?: (props: { - value: TFormData + onSubmit?: < + TFFormData extends TFormData, + TFOnMount extends undefined | FormValidateOrFn, + TFOnChange extends undefined | FormValidateOrFn, + TFOnChangeAsync extends undefined | FormAsyncValidateOrFn, + TFOnBlur extends undefined | FormValidateOrFn, + TFOnBlurAsync extends undefined | FormAsyncValidateOrFn, + TFOnSubmit extends undefined | FormValidateOrFn, + TFOnSubmitAsync extends undefined | FormAsyncValidateOrFn, + TFOnServer extends undefined | FormValidateOrFn, + TFSubmitMeta extends TSubmitMeta + >(props: { + value: TFFormData formApi: FormApi< - TFormData, - TOnMount, - TOnChange, - TOnChangeAsync, - TOnBlur, - TOnBlurAsync, - TOnSubmit, - TOnSubmitAsync, - TOnServer, - TSubmitMeta + TFFormData, + TFOnMount, + TFOnChange, + TFOnChangeAsync, + TFOnBlur, + TFOnBlurAsync, + TFOnSubmit, + TFOnSubmitAsync, + TFOnServer, + TFSubmitMeta > meta: TSubmitMeta }) => any | Promise /** * Specify an action for scenarios where the user tries to submit an invalid form. */ - onSubmitInvalid?: (props: { - value: TFormData + onSubmitInvalid?: < + TFFormData extends TFormData, + TFOnMount extends undefined | FormValidateOrFn, + TFOnChange extends undefined | FormValidateOrFn, + TFOnChangeAsync extends undefined | FormAsyncValidateOrFn, + TFOnBlur extends undefined | FormValidateOrFn, + TFOnBlurAsync extends undefined | FormAsyncValidateOrFn, + TFOnSubmit extends undefined | FormValidateOrFn, + TFOnSubmitAsync extends undefined | FormAsyncValidateOrFn, + TFOnServer extends undefined | FormValidateOrFn, + TFSubmitMeta extends TSubmitMeta + >(props: { + value: TFFormData formApi: FormApi< - TFormData, - TOnMount, - TOnChange, - TOnChangeAsync, - TOnBlur, - TOnBlurAsync, - TOnSubmit, - TOnSubmitAsync, - TOnServer, - TSubmitMeta + TFFormData, + TFOnMount, + TFOnChange, + TFOnChangeAsync, + TFOnBlur, + TFOnBlurAsync, + TFOnSubmit, + TFOnSubmitAsync, + TFOnServer, + TFSubmitMeta > }) => void - transform?: FormTransform< - NoInfer, - NoInfer, - NoInfer, - NoInfer, - NoInfer, - NoInfer, - NoInfer, - NoInfer, - NoInfer, - NoInfer - > + transform?: FormTransform> } /**