mirror of
https://github.com/element-plus/element-plus.git
synced 2025-08-26 04:27:26 +08:00
fix(components): [form] improve types (#12549)
* fix(components): [form] improve types * fix(components): [form] improve FormRules type, support object and array * fix(components): [form] improve FormRules type with comment * fix(components): [form] allow number as key in FormRules type * chore(components): [form] fix FormRules type example * chore: remove extra import * chore: update form/custom-validation and form/validation examples * chore(components): [form] update example
This commit is contained in:
@ -79,7 +79,7 @@ const ruleForm = reactive({
|
||||
age: '',
|
||||
})
|
||||
|
||||
const rules = reactive<FormRules>({
|
||||
const rules = reactive<FormRules<typeof ruleForm>>({
|
||||
pass: [{ validator: validatePass, trigger: 'blur' }],
|
||||
checkPass: [{ validator: validatePass2, trigger: 'blur' }],
|
||||
age: [{ validator: checkAge, trigger: 'blur' }],
|
||||
|
@ -83,9 +83,21 @@
|
||||
import { reactive, ref } from 'vue'
|
||||
import type { FormInstance, FormRules } from 'element-plus'
|
||||
|
||||
interface RuleForm {
|
||||
name: string
|
||||
region: string
|
||||
count: string
|
||||
date1: string
|
||||
date2: string
|
||||
delivery: boolean
|
||||
type: string[]
|
||||
resource: string
|
||||
desc: string
|
||||
}
|
||||
|
||||
const formSize = ref('default')
|
||||
const ruleFormRef = ref<FormInstance>()
|
||||
const ruleForm = reactive({
|
||||
const ruleForm = reactive<RuleForm>({
|
||||
name: 'Hello',
|
||||
region: '',
|
||||
count: '',
|
||||
@ -97,7 +109,7 @@ const ruleForm = reactive({
|
||||
desc: '',
|
||||
})
|
||||
|
||||
const rules = reactive<FormRules>({
|
||||
const rules = reactive<FormRules<RuleForm>>({
|
||||
name: [
|
||||
{ required: true, message: 'Please input Activity name', trigger: 'blur' },
|
||||
{ min: 3, max: 5, message: 'Length should be 3 to 5', trigger: 'blur' },
|
||||
|
@ -6,6 +6,7 @@ import type {
|
||||
} from 'async-validator'
|
||||
import type { ComponentSize } from '@element-plus/constants'
|
||||
import type { Arrayable } from '@element-plus/utils'
|
||||
import type { MaybeRef } from '@vueuse/core'
|
||||
import type {
|
||||
FormItemProp,
|
||||
FormItemProps,
|
||||
@ -19,7 +20,82 @@ export type FormLabelWidthContext = ReturnType<typeof useFormLabelWidth>
|
||||
export interface FormItemRule extends RuleItem {
|
||||
trigger?: Arrayable<string>
|
||||
}
|
||||
export type FormRules = Partial<Record<string, Arrayable<FormItemRule>>>
|
||||
|
||||
type Primitive = null | undefined | string | number | boolean | symbol | bigint
|
||||
/**
|
||||
* Check whether it is tuple
|
||||
*
|
||||
* 检查是否为元组
|
||||
*
|
||||
* @example
|
||||
* IsTuple<[1, 2, 3]> => true
|
||||
* IsTuple<Array[number]> => false
|
||||
*/
|
||||
type IsTuple<T extends ReadonlyArray<any>> = number extends T['length']
|
||||
? false
|
||||
: true
|
||||
/**
|
||||
* Array method key
|
||||
*
|
||||
* 数组方法键
|
||||
*/
|
||||
type ArrayMethodKey = keyof any[]
|
||||
/**
|
||||
* Tuple index key
|
||||
*
|
||||
* 元组下标键
|
||||
*
|
||||
* @example
|
||||
* TupleKey<[1, 2, 3]> => '0' | '1' | '2'
|
||||
*/
|
||||
type TupleKey<T extends ReadonlyArray<any>> = Exclude<keyof T, ArrayMethodKey>
|
||||
/**
|
||||
* Array index key
|
||||
*
|
||||
* 数组下标键
|
||||
*/
|
||||
type ArrayKey = number
|
||||
/**
|
||||
* Helper type for recursively constructing paths through a type
|
||||
*
|
||||
* 用于通过一个类型递归构建路径的辅助类型
|
||||
*/
|
||||
type PathImpl<K extends string | number, V> = V extends Primitive
|
||||
? `${K}`
|
||||
: `${K}` | `${K}.${Path<V>}`
|
||||
/**
|
||||
* Type which collects all paths through a type
|
||||
*
|
||||
* 通过一个类型收集所有路径的类型
|
||||
*
|
||||
* @see {@link FieldPath}
|
||||
*/
|
||||
type Path<T> = T extends ReadonlyArray<infer V>
|
||||
? IsTuple<T> extends true
|
||||
? {
|
||||
[K in TupleKey<T>]-?: PathImpl<Exclude<K, symbol>, T[K]>
|
||||
}[TupleKey<T>] // tuple
|
||||
: PathImpl<ArrayKey, V> // array
|
||||
: {
|
||||
[K in keyof T]-?: PathImpl<Exclude<K, symbol>, T[K]>
|
||||
}[keyof T] // object
|
||||
/**
|
||||
* Type which collects all paths through a type
|
||||
*
|
||||
* 通过一个类型收集所有路径的类型
|
||||
*
|
||||
* @example
|
||||
* FieldPath<{ 1: number; a: number; b: string; c: { d: number; e: string }; f: [{ value: string }]; g: { value: string }[] }> => '1' | 'a' | 'b' | 'c' | 'f' | 'g' | 'c.d' | 'c.e' | 'f.0' | 'f.0.value' | 'g.number' | 'g.number.value'
|
||||
*/
|
||||
type FieldPath<T> = T extends object ? Path<T> : never
|
||||
export type FormRules<
|
||||
T extends MaybeRef<Record<string, any> | string> = string
|
||||
> = Partial<
|
||||
Record<
|
||||
UnwrapRef<T> extends string ? UnwrapRef<T> : FieldPath<UnwrapRef<T>>,
|
||||
Arrayable<FormItemRule>
|
||||
>
|
||||
>
|
||||
|
||||
export type FormValidationResult = Promise<boolean>
|
||||
export type FormValidateCallback = (
|
||||
|
Reference in New Issue
Block a user