如何修复next-intl中useTranslations的链式命名空间类型推导问题
问题核心原因
你之前的类型定义没有将useTranslations传入的命名空间对应的子字典类型,传递给返回的翻译函数,翻译函数始终校验的是完整字典的所有路径,所以传入子路径"three"时,会匹配完整字典的一级key(只有"one"),自然抛出类型错误。
解决方案
需要新增两个工具类型:
DeepKeyOf<T>:递归生成目标对象所有合法属性路径的联合类型Get<T, Path>:根据传入的路径字符串,返回对象对应位置的属性类型
再调整useTranslations的类型定义,将命名空间对应的子字典类型,作为泛型传递给返回的翻译函数即可。
完整修改后代码
import type { ReactNode } from 'react'; import dict from "./locales/en" // 假设 useNextTranslations 是 next-intl 原生导出的方法 import { useTranslations as useNextTranslations } from 'next-intl'; type Dict = typeof dict; // 递归生成对象所有合法路径的联合类型 type DeepKeyOf<T> = T extends object ? { [K in keyof T & string]: K | `${K}.${DeepKeyOf<T[K]>}` }[keyof T & string] : never; // 根据路径字符串提取对象对应属性的类型 type Get<T, Path extends string> = Path extends `${infer K}.${infer Rest}` ? K extends keyof T ? Get<T[K], Rest> : never : Path extends keyof T ? T[Path] : never; // 翻译函数的类型,泛型 D 为当前需要匹配的字典类型 interface UseTranslationsReturn<D> { <S extends DeepKeyOf<D>>( key: S, values?: Record< string, | string | number | boolean | Date | ((children: ReactNode) => ReactNode) | null | undefined > ): string } // useTranslations 主函数的类型 interface UseTranslationsProps { <S extends DeepKeyOf<Dict>>(namespace?: S): UseTranslationsReturn<Get<Dict, S>> } export const useTranslations: UseTranslationsProps = (namespace) => useNextTranslations(namespace)
效果验证
// 场景1:不传命名空间 const t1 = useTranslations() const val1 = t1("one.two.three") // 类型合法,返回 "3" const val2 = t1("one.two.foo") // 类型合法,返回 "bar" t1("xxx") // 类型报错,提示无此路径 // 场景2:传入命名空间 const t2 = useTranslations("one.two") const val3 = t2("three") // 类型合法,返回 "3" const val4 = t2("foo") // 类型合法,返回 "bar" t2("one") // 类型报错,提示无此key
内容的提问来源于stack exchange,提问作者cnotethegr8
相关产品推荐
相关产品推荐

