You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在TypeScript中增强vue-i18n的useI18n返回的t函数的参数类型提示?

如何在TypeScript中增强vue-i18n的useI18n返回的t函数的参数类型提示?

嗨,我之前刚好遇到过一模一样的需求!不用直接修改vue-i18n的源码,只需要写一个简单的包装函数,结合TypeScript的泛型和类型工具就能实现你想要的效果——既保留原useI18n的所有功能,又给t函数加上额外的key类型提示。下面给你一步步讲清楚:

核心思路

我们的目标是:

  1. 保留原useI18n从传入的messages中自动推断key类型的能力
  2. 给t函数的key参数额外添加自定义的类型(比如你说的"aaa")
  3. 完全保留t函数原本的其他参数和返回值类型(比如插值、指定locale这些功能不能丢)

具体实现代码

首先,我们先导入vue-i18n的相关类型,然后定义包装函数:

import { useI18n, UseI18nOptions, UseI18nReturn } from "vue-i18n";

// 1. 先定义你想要添加的额外翻译key类型
type ExtraTranslationKeys = "aaa";

// 2. 写包装函数,用泛型保留原useI18n的类型推断能力
function useEnhancedI18n<
  Messages extends Record<string, any>,
  Locale = string,
  DefaultLocale = Locale
>(options: UseI18nOptions<Messages, Locale, DefaultLocale>) {
  // 调用原生的useI18n获取所有返回值
  const originalI18n = useI18n(options);

  // 3. 增强t函数的类型:把原始的key类型和额外key类型合并
  // 这里用TypeScript的Parameters和ReturnType工具类型,确保保留t函数的其他参数和返回值类型
  const enhancedT = originalI18n.t as (
    key: keyof Messages[Locale] | ExtraTranslationKeys,
    ...rest: Parameters<UseI18nReturn<Messages, Locale, DefaultLocale>["t"]> extends [any, ...infer RestArgs] ? RestArgs : never
  ) => ReturnType<typeof originalI18n.t>;

  // 4. 返回合并后的对象,替换t为增强版,其他属性完全保留
  return {
    ...originalI18n,
    t: enhancedT,
  };
}

怎么使用这个包装函数?

和你之前用原生useI18n的方式几乎一样,只是换成我们写的useEnhancedI18n

const { t } = useEnhancedI18n({
  messages: {
    zh: { title: "zh", test: "TEST" },
    en: { title: "en", test: "test" }
  }
});

// 现在输入t("")的时候,会自动提示title、test和aaa三个选项!
t("title"); // 正常工作,保留原类型推断
t("test"); // 同样正常
t("aaa"); // 新增的key也会有类型提示,不会报TypeScript错误

进阶优化(可选)

如果你希望额外的key也对应真实的多语言消息(而不只是类型提示),可以把ExtraTranslationKeys改成从额外的消息对象中提取key,这样更严谨:

// 定义额外的多语言消息
type ExtraMessages = {
  zh: { aaa: "中文测试aaa" },
  en: { aaa: "English test aaa" }
};

// 自动提取额外消息的key类型
type ExtraTranslationKeys = keyof ExtraMessages[string];

这样做的话,你还可以把额外消息合并到传入useEnhancedI18n的messages里,确保实际翻译也能生效:

const baseMessages = {
  zh: { title: "zh", test: "TEST" },
  en: { title: "en", test: "test" }
};

// 合并基础消息和额外消息
const mergedMessages = {
  zh: { ...baseMessages.zh, ...ExtraMessages.zh },
  en: { ...baseMessages.en, ...ExtraMessages.en }
};

const { t } = useEnhancedI18n({ messages: mergedMessages });

这样既保证了类型提示,又能让实际翻译正常工作~

内容来源于stack exchange

火山引擎 最新活动