我想将i18next
转换键声明为对象中的属性值,并以一种只接受有效i18next
转换键值的方式将其键入为Record<string, SomeType>
(只接受叶子,因为我不希望它接受有嵌套键的部分的键,这样当我将键传递给t()
时,结果总是一个字符串)。
我有这个代码(使用i18next
22.4和react-i18next
12.2)
import { useTranslation } from 'react-i18next';
import type { TFuncKey } from 'i18next';
// A map of paths to translation keys
// I want TS to complain here if I try to use a string that
// doesn't match a translation key matching a string.
// This below works otherwise but `TFuncKey` is a bit too loose type as
// it also accepts e.g. 'Navigation` which results in an object, not a string.
const pageTitles: Record<string, TFuncKey> = {
'/': 'Navigation.home', // note: plain string values here, not calling `t()`
'/about': 'Navigation.about',
'/other': 'Navigation.other',
};
function useTitle(path: string): string {
const { t } = useTranslation();
return pageTitles[path] ? t(pageTitles[path]) : t('ErrorMessages.error');
// The previous line currently gives a TS error because t(pageTitles[path]) may
// return an object (not matching the return type of string in this method)
}
字符串
我可以通过使用t(pageTitles[path]) as string
来解决这个错误,但它可能会在运行时中断,因为TFuncKey
类型有点太松散,我可能会不小心传递一个像''Navigation''
这样的值,当传递给t()
时,它不会产生字符串。
如果我像这样内联map对象,那么代码就可以正常工作:
function useTitle(path: string): string {
const { t } = useTranslation();
return {
'/': t('Navigation.home'), // note: calling `t()` here directly
'/about': t('Navigation.about'),
'/other': t('Navigation.other'),
}[path] ?? t('ErrorMessages.error');
}
型
但是我想重构Map,让它在其他地方声明(在这个React钩子之外),因为我的代码比这里的示例要复杂一些(并且路由更多)。所以如果可能的话,我希望它更像第一个例子,如果有可能修复类型,以使TS满意。
我不确定是否可以使用TFuncKey
的泛型或i18next
的其他类型来解决我的问题。
2条答案
按热度按时间osh3o9ms1#
只需升级到
i18next
23.x即可解决此问题。类型
TFuncKey
将需要替换为ParseKeys
,如迁移指南中所述(类型已重命名)。我最初使用的是
i18next 22.4
(和react-i18next
12.2),但升级到i18next
23.4(和react-i18next
13.0)后,上面的代码就像预期一样工作,因为如果试图使用'Navigation'
作为pageTitles
对象的值,它会抱怨。这是由于
i18next
23中重新设计的新类型和returnObjects
选项,该选项似乎全局默认为false
(也可以显式设置为每次调用t()
的选项)。lsmepo6l2#
make pageTitles const.
字符串