Vue-i18n结合TypeScript使用数组时遇类型错误求助
解决Vue-i18n数组元素类型推断为
never的TypeScript错误 问题分析
你遇到的Property 'code' does not exist on type 'never'错误,是因为TypeScript无法从JSON文件中正确推断出国家数组元素的具体类型。虽然已将MessageSchema基于enUS定义,但Vue-i18n的类型系统对数组的推断存在局限性,导致数组元素被缩小为never类型。
解决方案
方案1:显式扩展MessageSchema类型
在/boot/i18n.ts中,手动定义国家对象类型并扩展原有MessageSchema,明确数组的类型结构:
import enUS from 'src/i18n/en-US.json' import nlBE from 'src/i18n/nl-BE.json' // 定义国家对象的具体类型 type Country = { code: string name: string } // 扩展MessageSchema,覆盖countries字段的类型 type MessageSchema = Omit<typeof enUS, 'page'> & { page: Omit<typeof enUS['page'], 'landing'> & { landing: Omit<typeof enUS['page']['landing'], 'countries'> & { countries: Country[] } } } export default boot(({ app }) => { const i18n = createI18n<[MessageSchema], 'en-US' | 'nl-BE'>({ legacy: false, locale: Quasar.lang.getLocale(), fallbackLocale: 'en-US', // 断言消息结构符合MessageSchema messages: { 'en-US': enUS as MessageSchema, 'nl-BE': nlBE as MessageSchema }, }) app.use(i18n) })
方案2:添加JSON类型声明文件
创建src/i18n/index.d.ts,统一约束所有语言JSON文件的类型:
declare module '*.json' { export interface Country { code: string name: string } export interface MessageSchema { page: { landing: { title: { selectCountry: string } countries: Country[] } } // 补充其他语言字段的类型定义 } const value: MessageSchema export default value }
随后在/boot/i18n.ts中导入该类型:
import enUS from 'src/i18n/en-US.json' import nlBE from 'src/i18n/nl-BE.json' import type { MessageSchema } from 'src/i18n' export default boot(({ app }) => { const i18n = createI18n<[MessageSchema], 'en-US' | 'nl-BE'>({ legacy: false, locale: Quasar.lang.getLocale(), fallbackLocale: 'en-US', messages: { 'en-US': enUS, 'nl-BE': nlBE }, }) app.use(i18n) })
方案3:组件内局部类型断言
如果不想修改全局类型,可在LandingPage.vue中对$tm的返回值做类型断言:
<template> <q-page> <div> <q-card v-for="country in countries" :key="country.code"> <q-card-section> <div> {{ $rt(country.name) }} </div> </q-card-section> </q-card> </div> </q-page> </template> <script setup lang="ts"> interface Country { code: string name: string } // 显式指定数组元素类型 const countries = $tm('page.landing.countries') as Country[] </script>
原理说明
TypeScript对JSON文件的类型推断依赖静态分析,当数组元素类型无法被明确识别时(比如多语言文件存在潜在结构差异),会将元素类型缩小为never。通过显式定义类型,给TypeScript提供明确的类型上下文,即可解决属性不存在的错误。
内容的提问来源于stack exchange,提问作者DarkLite1
相关产品推荐
相关产品推荐

