You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 14:33:12