如何为i18next叶子翻译键定义严格TypeScript类型
解决方案
要实现仅允许叶子翻译键(调用t()返回字符串的键)的路由映射类型约束,你可以通过递归提取翻译资源的叶子键路径来定义严格的类型,替代宽松的TFuncKey。
步骤1:定义翻译资源类型
首先从你的i18n配置或翻译文件中获取翻译资源的TypeScript类型:
// 方式1:直接从翻译文件导入类型 type TranslationResources = typeof import('./locales/en.json'); // 方式2:从已初始化的i18n实例获取 import i18n from './i18n'; type TranslationResources = typeof i18n.options.resources['en'];
步骤2:编写递归类型提取叶子键
创建一个递归类型,遍历翻译资源结构,仅收集最终对应字符串值的完整键路径(如'Navigation.home'):
type LeafTranslationKeys<T> = T extends string ? '' // 叶子节点(值为字符串),返回空字符串终止递归 : { [K in keyof T]: K extends string ? `${K}${LeafTranslationKeys<T[K]> extends '' ? '' : `.${LeafTranslationKeys<T[K]>}`}` : never; }[keyof T];
步骤3:定义严格的路由映射类型
用LeafTranslationKeys约束映射对象的值类型,确保仅接受合法的叶子翻译键:
// 路由到翻译键的映射类型 type RouteTranslationMap = Record<string, LeafTranslationKeys<TranslationResources>>; // 合法示例:仅使用叶子键 const routeTranslations: RouteTranslationMap = { '/': 'Navigation.home', '/profile': 'Navigation.profile', '/submit': 'Button.submit' }; // 非法示例:TypeScript会直接报错(父级键'Navigation'不被允许) // const invalidMap: RouteTranslationMap = { // '/': 'Navigation' // };
原理说明
- 递归类型
LeafTranslationKeys会逐层遍历翻译资源的嵌套结构,只有当某个键的最终值是字符串时,才会生成对应的完整键路径类型。 - 相比
TFuncKey允许父级键(对应对象值),这个类型严格限制了仅能使用会返回字符串的叶子键,彻底避免了运行时调用t()返回对象的风险。 - 映射对象可以完全在React Hook外部声明,无需内联在组件或Hook逻辑中。
内容的提问来源于stack exchange,提问作者Haprog
相关产品推荐
相关产品推荐

