Vue3+TypeScript中Vuelidate字段组件Prop类型设置问题
问题
在Vue3+TypeScript项目中使用Vuelidate做表单校验时,尝试将v$.[keyField]这类单个字段的校验对象传递给InputValidationWrapper组件的validationField Prop,但设置NestedValidations类型后,访问validationField.$dirty、validationField.email.$invalid时会抛出类型错误:Property '$dirty' does not exist on type NestedValidations<ValidationArgs<unknown>, unknown>。相关代码如下:
SignInView.vue
<template> <div class="sign-in-view"> <form @submit.prevent="onSubmit" class="sign-in-form"> <div class="inputs-container"> <InputValidationWrapper :validationField="v$.email" required email> <BaseInput title="Email" v-model="formData.email" /> </InputValidationWrapper> </div> <button type="submit">submit</button> </form> </div> </template> <script setup lang="ts"> import BaseInput from "@/components/inputs/BaseInput.vue"; import InputValidationWrapper from "@/components/validators/InputValidationWrapper.vue"; import useVuelidate from "@vuelidate/core"; import { required, email } from "@vuelidate/validators"; import { computed, reactive } from "vue"; const formData = reactive({ email: "", password: "", }); const validationRules = computed(() => { return { email: { required, email }, password: { required }, }; }); const v$ = useVuelidate(validationRules, formData); const onSubmit = async () => { const result = await v$.value.$validate(); if (!result) return; console.log("submit"); }; </script>
InputValidationWrapper.vue
<template> <div class="input-wrapper"> <slot /> <div class="errors-block"> <RequiredValidation :isDirty="validationField.$dirty" :isInvalid="validationField.required.$invalid" v-if="required" /> <EmailValidation :isDirty="validationField.$dirty" :isInvalid="validationField.email.$invalid" v-if="email" /> </div> </div> </template> <script setup lang="ts"> import RequiredValidation from "./RequiredValidation.vue"; import EmailValidation from "./EmailValidation.vue"; import type { NestedValidations } from "@vuelidate/core/index.js"; type PropsType = { validationField: NestedValidations; // 此处类型错误 required?: boolean; email?: boolean; }; defineProps<PropsType>(); </script>
解决方案
1. 使用正确的类型:FieldValidation
NestedValidations是用于嵌套结构的校验对象(比如表单对象中包含子对象的场景),而单个字段的校验对象应该使用Vuelidate提供的FieldValidation类型,该类型包含$dirty、$invalid等公共校验状态属性,同时可以包含对应校验规则的子属性。
2. 修改InputValidationWrapper的类型定义
更新InputValidationWrapper.vue中的类型导入和Props定义:
<template> <!-- 模板部分不变 --> </template> <script setup lang="ts"> import RequiredValidation from "./RequiredValidation.vue"; import EmailValidation from "./EmailValidation.vue"; // 导入FieldValidation类型 import type { FieldValidation } from '@vuelidate/core' // 定义包含所需校验规则的字段校验类型 type ValidationField = FieldValidation & { required?: { $invalid: boolean } email?: { $invalid: boolean } } type PropsType = { validationField: ValidationField required?: boolean email?: boolean } defineProps<PropsType>() </script>
3. 更通用的写法(可选)
如果需要支持更多校验规则,可以扩展ValidationField类型,或者直接使用泛型来匹配具体的校验规则结构:
import type { FieldValidation, ValidationRule } from '@vuelidate/core' // 定义支持的校验规则类型 type SupportedRules = { required?: ValidationRule email?: ValidationRule } type ValidationField = FieldValidation<SupportedRules> type PropsType = { validationField: ValidationField required?: boolean email?: boolean }
效果说明
修改后,TypeScript将正确识别validationField.$dirty、validationField.required.$invalid等属性,不再抛出类型错误,同时保留类型校验的安全性。
内容的提问来源于stack exchange,提问作者Alexey
相关产品推荐
相关产品推荐

