如何键入应与 i18next 翻译键匹配的字符串,该 i18next 翻译键与字符串而不是嵌套对象匹配?

问题描述 投票:0回答:1

我想将

i18next
翻译键声明为对象中的属性值,并将其键入为
Record<string, SomeType>
,使其仅接受有效
i18next
翻译键的值(仅叶子,因为我不想要它)接受具有嵌套键的部分的键,以便当我将键传递给
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()

如果我像这样内联地图对象,那么代码将按预期工作:

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');
}

但我想重构要在其他地方(在此 React 钩子之外)声明的映射,我不能使用

useTranslation()
,因为我的实际代码比此处的示例更复杂(并且有更多路线)。因此,如果可能的话,如果可以修复打字以便 TS 满意的话,我希望它更像第一个示例。

我不确定是否可以使用

TFuncKey
的泛型或
i18next
中的其他类型来解决我的问题。

reactjs typescript i18next react-i18next
1个回答
0
投票

使页面标题常量。

const pageTitles = {
  '/': 'Navigation.home',
  '/about': 'Navigation.about',
  '/other': 'Navigation.other',
} as const;
© www.soinside.com 2019 - 2024. All rights reserved.