validierung
Version:
Vue Composition Function for Form Validation
378 lines (368 loc) • 9.52 kB
TypeScript
import { Ref, UnwrapRef, ComputedRef } from 'vue-demi'
declare type AnyFunction = (...args: any[]) => any
declare type DeepIndex<
T,
Keys extends readonly PropertyKey[],
R = unknown
> = Keys extends [infer First, ...infer Rest]
? First extends keyof T
? Rest extends readonly PropertyKey[]
? DeepIndex<T[First], Rest>
: R
: R
: T
declare type MaybeRef<T> = T extends Ref<infer V> ? T | V : Ref<T> | T
declare type ExcludePrimitives<T> = T extends AnyFunction
? never
: T extends object
? T
: never
declare type DeepPartial<T extends object> = T extends readonly any[]
? {
[K in keyof T]: DeepPartialImpl<T[K]>
}
: {
[K in keyof T]?: DeepPartialImpl<T[K]> | undefined
}
declare type DeepPartialImpl<T> = T extends AnyFunction
? T
: T extends object
? DeepPartial<T>
: T
declare type ValidationBehaviorString = keyof ValidationBehaviorFunctions
interface ValidationBehaviorFunctions {}
declare type ValidationBehaviorInfo<T = any> = {
/**
* `True` if the paired rule of this behavior has an error.
*/
hasError: boolean
/**
* The touched state of the field.
*/
touched: boolean
/**
* The dirty state of the field.
*/
dirty: boolean
/**
* `True` if the validation was triggered with the `force` flag.
*/
force: boolean
/**
* `True` if the validation was triggered with the `submit` flag.
*/
submit: boolean
/**
* The `$value` property of the field.
*/
value: T
}
declare type ValidationBehaviorFunction = (
info: ValidationBehaviorInfo
) => boolean
declare type ValidationBehavior =
| ValidationBehaviorString
| ValidationBehaviorFunction
declare type SimpleRule<Param = any> = (...value: Param[]) => any
declare type KeyedRule<Params extends readonly any[] = any[]> = (
...values: [...Params]
) => any
declare type RuleWithKey<T extends readonly any[] = any[]> = {
key: string
rule?: KeyedRule<T>
}
declare type FieldSimpleRule<Param = any> =
| SimpleRule<Param>
| [
validationBehavior: ValidationBehavior,
rule: SimpleRule<Param>,
debounce?: number
]
| [rule: SimpleRule<Param>, debounce: number]
declare type FieldRuleWithKey<Params extends readonly any[]> =
| RuleWithKey<Params>
| [
validationBehavior: ValidationBehavior,
rule: RuleWithKey<Params>,
debounce?: number
]
| [rule: RuleWithKey<Params>, debounce: number]
declare type FieldRule<
SimpleParam,
KeyedParams extends readonly any[] = any[]
> = FieldSimpleRule<UnwrapRef<SimpleParam>> | FieldRuleWithKey<KeyedParams>
declare type ValidateFieldsPredicateParameter = {
key: string
value: any
path: string[]
}
declare type ValidateFieldsPredicate = (
value: ValidateFieldsPredicateParameter
) => boolean
declare type Field<T, E extends object = Record<string, never>> = {
/**
* The field's default value.
*/
$value: MaybeRef<T>
/**
* Rules to use for validation.
*/
$rules?: FieldRule<T>[]
} & (E extends Record<string, never> ? unknown : E)
declare type ValidateOptions = {
/**
* Set the field touched when called.
*
* @default true
*/
setTouched?: boolean
/**
* Validate with the `force` flag set.
*
* @default true
*/
force?: boolean
}
declare type TransformedField<T, E extends object = Record<string, never>> = {
/**
* The unique id of this field.
*/
$uid: number
/**
* The current field's value.
*/
$value: T
/**
* A list of validation error messages.
*/
$errors: string[]
/**
* The error status of this field.
*/
$hasError: boolean
/**
* `True` while this field has any pending rules.
*/
$validating: boolean
/**
* `True` if the field is touched. In most cases,
* this value should be set together with the `blur` event.
* Either through `$validate` or manually.
*/
$touched: boolean
/**
* `True` if the `$value` of this field has changed at least once.
*/
$dirty: boolean
/**
* Validate this field.
*
* @param options - Validate options to use
* @default
* ```
* { setTouched: true, force: true }
* ```
*/
$validate(options?: ValidateOptions): Promise<void>
} & (E extends Record<string, never> ? unknown : UnwrapRef<E>)
/**
* Unwrap the `$value` property of all fields in `FormData`.
*/
declare type ResultFormData<FormData> = FormData extends any
? {
[K in keyof FormData]: ResultFormDataImpl<FormData[K]>
}
: never
declare type ResultFormDataImpl<T> = T extends {
$value: infer V
}
? UnwrapRef<Exclude<MaybeRef<V>, Ref>>
: T extends object
? ResultFormData<T>
: T
/**
* Receive the name of every field in `FormData` as a union of strings.
*/
declare type FieldNames<FormData extends object> = FieldNamesImpl<
FormData,
never
>
declare type FieldNamesImpl<FormData, K> =
ExcludePrimitives<FormData> extends never
? never
: FormData extends {
$value: any
}
? K
: FormData extends readonly (infer A)[]
? FieldNamesImpl<A, K>
: {
[K in keyof FormData]-?: ExcludePrimitives<FormData[K]> extends {
$value: any
}
? K
: FieldNamesImpl<ExcludePrimitives<FormData[K]>, K>
}[keyof FormData]
/**
* Transforms every field in `FormData` into transformed fields.
*/
declare type TransformFormData<FormData> = FormData extends any
? {
[K in keyof FormData]: TransformFormDataImpl<FormData[K]>
}
: never
declare type TransformFormDataImpl<T> = T extends {
$value: infer V
}
? TransformedField<
UnwrapRef<Exclude<MaybeRef<V>, Ref>>,
Omit<T, '$value' | '$rules'>
>
: T extends object
? TransformFormData<T>
: T
/**
* Vue composition function for form validation.
* For type inference in `useValidation` make sure to define the structure of your
* form data upfront and pass it as the generic parameter `FormData`.
*
* @param formData - The structure of your form data
*
* @example
* ```
* type FormData = {
* name: Field<string>,
* password: Field<string>
* }
*
* const { form } = useValidation<FormData>({
* name: {
* $value: '',
* $rules: []
* },
* password: {
* $value: '',
* $rules: []
* }
* })
* ```
*/
declare function useValidation<FormData extends object>(
formData: FormData
): UseValidation<FormData>
declare type UseValidation<FormData extends object> = {
/**
* A transformed reactive form data object.
*/
form: TransformFormData<FormData>
/**
* `True` during validation after calling `validateFields` when there were rules returning a `Promise`.
*/
submitting: Ref<boolean>
/**
* `True` while the form has any pending rules.
*/
validating: ComputedRef<boolean>
/**
* `True` if the form has any error.
*/
hasError: ComputedRef<boolean>
/**
* All current validation error messages.
*/
errors: ComputedRef<string[]>
/**
* Validate all fields and return a `Promise` containing the resulting form data.
*
* @param options - Options to use for validation
* @throws `ValidationError`
*/
validateFields(options?: {
/**
* A list of field names to validate.
*
* @default
* ```
* undefined // meaning validate all
* ```
*/
names?: FieldNames<FormData>[]
/**
* Filter which values to keep in the resulting form data.
* Used like `Array.prototype.filter` but for objects.
*
* @default
* ```
* () => true // meaning keep all
* ```
*/
predicate?: ValidateFieldsPredicate
}): Promise<ResultFormData<FormData>>
/**
* Reset all fields to their default value or pass an object to set specific values.
* It will not create any new fields not present in the form data initially.
*
* @param formData - Form data to set specific values. It has the same structure as the object passed to `useValidation`
*/
resetFields(formData?: DeepPartial<ResultFormData<FormData>>): void
/**
* Adds a new property to the form data.
* Fields with a `$value` are transformed.
*
* @param path - A path of `string` and `numbers`
* @param value - The value to add at the specified path
*/
add<Keys extends readonly (string | number)[]>(
path: readonly [...Keys],
value: DeepIndex<FormData, Keys> extends (infer TArray)[]
? TArray
: DeepIndex<FormData, Keys>
): void
/**
* Removes a property from the form data.
*
* @param path - A path of `string` and `numbers` to the property to remove
*/
remove(path: (string | number)[]): void
}
declare type Configuration = {
defaultValidationBehavior: ValidationBehaviorString
validationBehavior: {
[K in ValidationBehaviorString]: ValidationBehaviorFunction
}
}
declare type Validation = {
install(): void
}
/**
* Configure the validation behavior of `useValidation`.
*
* @param configuration - The form validation configuration
*/
declare function createValidation(configuration: Configuration): Validation
declare class ValidationError extends Error {
constructor()
}
export {
DeepPartial,
Field,
FieldNames,
KeyedRule,
ResultFormData,
SimpleRule,
TransformFormData,
TransformedField,
UseValidation,
ValidateFieldsPredicate,
ValidateFieldsPredicateParameter,
ValidateOptions,
Validation,
ValidationBehavior,
ValidationBehaviorFunction,
ValidationBehaviorFunctions,
ValidationBehaviorInfo,
ValidationBehaviorString,
ValidationError,
createValidation,
useValidation
}