从Pinia状态向模板传数据时出现TypeScript类型错误
我用TypeScript开发Vue项目时,尝试将Pinia Store中的数据传递给子组件输入字段,遇到了类型错误,错误提示如下:
Property 'storeForm' does not exist on type '{ $: ComponentInternalInstance; $data: {}; $props: Partial<{}> & Omit<Readonly<ExtractPropTypes<{}>> & VNodeProps & AllowedComponentProps & ComponentCustomProps, never>; ... 10 more ...; $watch<T extends string | ((...args: any) => any)>(source: T, cb: T extends (...args: any) => infer R ? (args_0: R, args_1: R) => ...'.
请问是否需要为Store或其他属性添加类型定义?相关代码如下:
子组件代码
<template> <v-sheet width="300" class="mx-auto"> <v-form fast-fail @submit.prevent> <!-- v-model="firstName" --> <v-text-field label="First name" :rules="firstNameRules" placeholder="Your Name" >{{ storeForm.firstName }}</v-text-field> <!-- 错误出现行 --> <!-- v-model="lastName" --> <v-text-field label="Last name" :rules="lastNameRules" >{{ storeForm.lastName }}</v-text-field> <v-btn type="submit" block class="mt-2" @click="submit($event)">Submit</v-btn> </v-form> </v-sheet> </template> <script lang="ts"> import { ref } from 'vue' import {useForm} from '@/stores/form' import router from '../router' import { defineComponent } from 'vue' export default defineComponent({ setup() { const storeForm = useForm(); // 获取Store实例 const firstName = ref<string>('') const lastName = ref<string>('') const firstNameRules = ref<any>( (value: String) => { if (value?.length > 3) return true return 'First name must be at least 3 characters.' } ) const lastNameRules = ref<any>( (value: String) => { if (/[^0-9]/.test(String(value))) return true return 'Last name can not contain digits.' } ) const submit = (event: Event) => { event.preventDefault(); let user = { firstName: firstName.value, lastName: lastName.value, } storeForm.login(user) router.push('/'); firstName.value = ''; lastName.value = ''; } return {firstName, lastName, firstNameRules, lastNameRules, submit}; } }) </script>
Store文件代码
import { defineStore } from 'pinia' export const useForm = defineStore('login',{ state: () => ({ firstName: <string>'', // 定义字符串类型 lastName: <string>'' }), getters: { }, actions: { login(data: any) { this.firstName = data.firstName this.lastName = data.lastName } } })
问题原因
你在setup()函数中声明了storeForm变量,但未将其返回给模板,导致模板无法识别该变量,TypeScript因此抛出“storeForm不存在”的类型错误。此问题与Store本身的类型定义无关。
解决步骤
在setup返回对象中添加storeForm
修改子组件的setup()返回值,将storeForm包含进去:return { firstName, lastName, firstNameRules, lastNameRules, submit, storeForm };优化Store类型定义(可选但推荐)
当前Store的login方法参数data为any类型,建议定义明确的类型以提升TypeScript校验能力:import { defineStore } from 'pinia' // 定义用户数据类型 interface UserData { firstName: string; lastName: string; } export const useForm = defineStore('login', { state: () => ({ firstName: '' as string, lastName: '' as string }), actions: { login(data: UserData) { this.firstName = data.firstName this.lastName = data.lastName } } })优化组件内规则类型(可选)
组件中firstNameRules和lastNameRules使用了ref<any>,可改为更精确的类型:// 表单验证规则类型 type FormRule = (value: string) => boolean | string; const firstNameRules = ref<FormRule>( (value: string) => { if (value?.length > 3) return true return 'First name must be at least 3 characters.' } ) const lastNameRules = ref<FormRule>( (value: string) => { if (/[^0-9]/.test(value)) return true return 'Last name can not contain digits.' } )
内容的提问来源于stack exchange,提问作者user20984971

