Vue3+TS报错属性不存在于'Ref<never[]>[]'类型的原因及解决方法
报错原因
触发这个TS报错有两个直接原因:
- 返回值类型推断不符合预期:你在
useShop中返回的是普通数组[shop, getShop],TS会默认把它推断为元素类型是联合类型的数组,也就是(Ref<never[]> | ((id: number) => Promise<void>))[]——这种类型只会标记数组里的元素是两种类型之一,不会记录每个索引位置对应的具体类型。 - 解构方式不匹配:你在组件中用对象解构的方式取值,但普通数组实例上根本不存在
shop、getShop这两个命名属性,TS自然会提示属性不存在。
另外还有个隐藏的类型问题:ref([])如果不传泛型指定类型,会被默认推断为Ref<never[]>,后续给shop.value赋值普通对象数组时也会报类型错误。
修复方案
优先选第一种方案,是Vue组合式函数的通用最佳实践:
方案1:改为返回对象(推荐)
组合式函数返回对象是官方推荐的写法,完全不需要额外处理类型推断,解构时按属性名取值也不会出现顺序错配问题。
修改useShop.ts代码:
// useShop.ts import { ref } from "vue" // 按业务实际定义店铺数据类型 interface ShopInfo { id: number name: string // 其余业务字段自行补充 } export default function useShop() { // 给ref传入泛型指定类型,避免被推断为never[] const shop = ref<ShopInfo[]>([]) const getShop = async (id: number) => { // 实际接口请求逻辑 shop.value = [] } // 改为返回对象 return { shop, getShop } }
修改后Detail.vue里的对象解构代码可以直接正常运行,不需要调整。
方案2:保留数组返回值,标注元组类型+改数组解构
如果有特殊场景必须返回数组,需要手动把返回值标记为元组类型,同时组件里改用数组解构:
首先修改useShop.ts:
// useShop.ts import { ref } from "vue" interface ShopInfo { id: number name: string } export default function useShop() { const shop = ref<ShopInfo[]>([]) const getShop = async (id: number) => { shop.value = [] } // 用as const或者手动标注元组类型,固定每个位置的类型 return [shop, getShop] as const // 也可以写为 return [shop, getShop] as [typeof shop, typeof getShop] }
然后修改Detail.vue里的解构方式,必须用数组解构,且顺序和返回顺序完全一致:
// Detail.vue export default defineComponent({ components: {}, setup() { // 数组解构,注意顺序不能乱 const [shop, getShop] = useShop() return { shop, getShop } }, })
注意:数组解构强依赖返回值的顺序,后续如果调整
useShop里返回值的顺序,所有用到的地方都要同步修改,维护成本更高,非必要不选这个方案。
内容的提问来源于stack exchange,提问作者Goryyn
相关产品推荐
相关产品推荐

