diff --git a/packages/core/src/composables/useForm.ts b/packages/core/src/composables/useForm.ts index 639ed00..ef7f3f7 100644 --- a/packages/core/src/composables/useForm.ts +++ b/packages/core/src/composables/useForm.ts @@ -20,6 +20,7 @@ import type { FieldAttrs, FieldError, FieldMeta, + FieldValidator, FormErrors, FormEventHandler, FormResetState, @@ -40,7 +41,7 @@ import type { interface FieldRegistry { [field: string]: { - validate: (value: any) => string | Promise | boolean | undefined; + validate: FieldValidator; }; } @@ -240,9 +241,11 @@ export function useForm< name: MaybeRefOrGetter, { validate }: any = {}, ) => { - fieldRegistry[toValue(name)] = { - validate, - }; + if (validate) { + fieldRegistry[toValue(name)] = { + validate, + }; + } }; const registerFieldArray = (name: MaybeRefOrGetter, options: any) => { @@ -469,28 +472,32 @@ export function useForm< }, }; - const runSingleFieldValidateHandler = (name: string, value: unknown) => { - return new Promise((resolve) => - resolve(fieldRegistry[name].validate(value) as string), - ); + const runSingleFieldValidateHandler = < + Name extends Path, + Value extends PathValue, + >( + name: Name, + value: Value, + ) => { + return Promise.resolve(fieldRegistry[name].validate(value)); }; const runFieldValidateHandler = (values: Values) => { const fieldKeysWithValidation = keysOf(fieldRegistry).filter((field) => isFunction(fieldRegistry[field].validate), - ) as string[]; + ) as Path[]; const fieldValidatePromise = fieldKeysWithValidation.map((field) => runSingleFieldValidateHandler(field, get(values, field)), ); return Promise.all(fieldValidatePromise).then((errors) => - errors.reduce((prev, curr, index) => { + errors.reduce((prev: FormErrors, curr, index) => { if (curr) { set(prev, fieldKeysWithValidation[index], curr); } return prev; - }, {} as FormErrors), + }, {}), ); }; @@ -610,16 +617,20 @@ export function useForm< }; }; - const validateField: ValidateField = (name) => { + const validateField: ValidateField = async (name) => { if (fieldRegistry[name] && isFunction(fieldRegistry[name].validate)) { dispatch({ type: ACTION_TYPE.SET_ISVALIDATING, payload: true }); - return runSingleFieldValidateHandler(name, get(state.values, name)) - .then((error) => { - setFieldError(name, error); - }) - .finally(() => { - dispatch({ type: ACTION_TYPE.SET_ISVALIDATING, payload: false }); - }); + + const value = get(state.values, name) as PathValue; + const error = (await runSingleFieldValidateHandler( + name, + value, + )) as FieldError>; + + setFieldError(name, error); + dispatch({ type: ACTION_TYPE.SET_ISVALIDATING, payload: false }); + + return error; } return Promise.resolve(); }; diff --git a/packages/core/src/types.ts b/packages/core/src/types.ts index 7b4989c..20b8e5b 100644 --- a/packages/core/src/types.ts +++ b/packages/core/src/types.ts @@ -101,13 +101,13 @@ export type ValidateField = < Name extends Path, >( name: Name, -) => Promise; +) => Promise> | void>; export type UseFormSetFieldError = < Name extends Path, >( name: Name, - error: FieldError> | string | string[], + error: FieldError>, ) => void; export type UseFormSetFieldTouched = <