使用带类型的JSON对象时TypeScript抛出警告问题排查
问题
使用Hook通过方括号表示法获取JSON对象属性时功能正常,但TypeScript持续抛出警告:
Property 'github' does not exist on type 'PropertyValues'
相关代码与配置
useI18n.ts
import { useRouter } from "next/router" import i18n from "i18n/index.json" type JSONRaw = typeof i18n type Name = keyof JSONRaw type Language = keyof JSONRaw[Name] type Selection = JSONRaw[Name] type Property = Pick<Selection, Language> type PropertyValues = Property[Language] export default function useI18n (name: Name) { const { locale } = useRouter() const JSONFile: JSONRaw = i18n const wantedTextList = JSONFile[name] const localeLanguage = locale as Language const value = wantedTextList[localeLanguage] return value as PropertyValues }
i18n/index.json
{ "header": { "es-ar": { "text": "lorem ipsum 2." }, "en-us": { "text": "lorem ipsum." } }, "preferences": { "es-ar": { "text": "lorem ipsum 2" }, "en-us": { "text": "lorem ipsum" } }, "notavaible": { "es-ar": { "text": "lorem ipsum 2" }, "en-us": { "text": "lorem ipsum" } }, "postnav": { "en-us": { "github": "lorem ipsum 2", "edit": " lorem ipsum" }, "es-ar": { "github": "lorem ipsum 2", "edit": "lorem ipsum" } } }
Hook使用方式
const { github, edit } = useI18n('postnav')
需求:获得正确的类型支持,并实现轻松扩展。
解决方案
问题出在当前类型定义未根据传入的name参数动态推导返回值类型,PropertyValues被推断为所有语言属性值的交集,导致TypeScript无法识别特定模块的专属属性。
修改useI18n的类型定义,通过泛型让TypeScript根据传入的name精确推导返回类型:
import { useRouter } from "next/router" import i18n from "i18n/index.json" // 原始JSON结构类型 type JSONRaw = typeof i18n; // 所有可用的模块名称 type ModuleName = keyof JSONRaw; // 给定模块下的语言类型 type Language<M extends ModuleName> = keyof JSONRaw[M]; // 给定模块+语言对应的属性值类型 type ModuleValues<M extends ModuleName> = JSONRaw[M][Language<M>]; // 泛型函数:根据传入的模块名推导返回值类型 export default function useI18n<M extends ModuleName>(name: M): ModuleValues<M> { const { locale } = useRouter(); const targetModule = i18n[name]; // 断言locale属于当前模块的语言集合(需确保项目locale配置与JSON一致) const currentLocale = locale as Language<M>; return targetModule[currentLocale]; }
关键优化点
- 泛型参数绑定:通过
M extends ModuleName绑定传入的模块名,TypeScript能精准识别对应模块的属性结构。 - 类型直接映射:
ModuleValues<M>直接指向对应模块下当前语言的具体属性类型,比如传入'postnav'时,返回类型会自动包含github和edit属性。 - 简化类型结构:移除冗余的中间类型定义,保留对JSON结构的强约束,后续扩展模块或属性时,类型会自动同步更新。
修改后,使用useI18n('postnav')解构github和edit时,TypeScript不再抛出警告,且后续扩展JSON内容无需手动修改类型定义,满足可扩展性需求。
内容的提问来源于stack exchange,提问作者Lazaro
相关产品推荐
相关产品推荐

