Vue3+TypeScript使用Provide/Inject遇TS2339类型错误求助
Vue3 + TypeScript Provide/Inject 类型错误(TS2339)解决办法
问题根源
inject函数返回的类型默认包含undefined(TypeScript无法保证父组件必然提供对应依赖),直接解构对象属性时,TS会判定属性可能不存在,从而抛出TS2339错误。
解决办法
1. 给inject设置默认值
如果允许子组件在未注入时使用兜底值,直接给inject传入第二个参数作为默认值,TS会自动排除undefined类型:
<!-- 子组件 --> <script setup lang="ts"> import { inject } from 'vue' // 定义类型接口,替换成你的实际类型 interface QueryState { error: Error | null loading: boolean interactions: any[] } const queryState = inject<QueryState>('queryState', { error: null, loading: false, interactions: [] }) // 解构不再报错 const { error, loading, interactions } = queryState </script>
2. 使用非空断言(!)
如果你能100%确保父组件一定会提供该依赖,可以用非空断言告诉TS这个值不会是undefined:
<!-- 子组件 --> <script setup lang="ts"> import { inject } from 'vue' interface QueryState { error: Error | null loading: boolean interactions: any[] } // 用!断言值必然存在 const queryState = inject<QueryState>('queryState')! const { error, loading, interactions } = queryState </script>
注意:如果父组件实际未提供依赖,运行时会抛出错误,仅在确定依赖必传时使用。
3. 结合InjectionKey做类型强校验
先在公共文件定义InjectionKey,让父组件和子组件共用这个类型标记,TS会自动校验类型匹配:
// types.ts import { InjectionKey, Ref } from 'vue' export interface QueryState { error: Ref<Error | null> loading: Ref<boolean> interactions: Ref<any[]> } export const queryStateKey: InjectionKey<QueryState> = Symbol('queryState')
父组件提供依赖时使用这个key:
<!-- 父组件 --> <script setup lang="ts"> import { provide, ref } from 'vue' import { queryStateKey } from './types' const error = ref<Error | null>(null) const loading = ref(false) const interactions = ref<any[]>([]) // 异步查询逻辑示例 const fetchData = async () => { loading.value = true try { const res = await fetch('/api/interactions') interactions.value = await res.json() } catch (err) { error.value = err as Error } finally { loading.value = false } } fetchData() // 用类型key提供值 provide(queryStateKey, { error, loading, interactions }) </script>
子组件注入时使用同一个key,TS会自动推导类型,且父组件未提供时会在编译阶段提示:
<!-- 子组件 --> <script setup lang="ts"> import { inject } from 'vue' import { queryStateKey } from './types' // 用key注入,类型自动匹配 const queryState = inject(queryStateKey)! const { error, loading, interactions } = queryState </script>
4. 可选链+空值合并处理
如果不确定父组件是否提供依赖,又不想用默认值,可以用可选链和空值合并规避报错:
<!-- 子组件 --> <script setup lang="ts"> import { inject } from 'vue' interface QueryState { error: Error | null loading: boolean interactions: any[] } const queryState = inject<QueryState>('queryState') // 解构时用可选链+空值合并兜底 const { error = null, loading = false, interactions = [] } = queryState ?? {} </script>
内容的提问来源于stack exchange,提问作者ZheFrench
相关产品推荐
相关产品推荐

