如何重构Fields类型为翻译库getTranslations函数增强类型安全
实现类型安全的翻译库:增强getTranslations的类型检查能力
我想要构建一个具备完整类型安全的翻译库,目前已有部分实现代码。当前getTranslations函数的context和field参数为string类型,调用时传入无效参数(比如getTranslations('de', 'bar', 'baz'))无法在编译期或编辑器中发现错误,也无法触发编辑器自动补全。请问如何重构Fields类型,以增强该函数的类型安全性?
现有代码
// 想要新增语言?直接加 "| 'gr'" 即可 type Lang = "de" | "en"; type Fields = { // 可以为每个新上下文定义子条目,比如history、orderManagement、vehicleDetails等,按需添加 history: { historyEntry: string; locationChanged: string; manuallyCreated: string; }; orderManagement: { // 新增翻译字符串时,直接加一个string类型的字段即可 order: string; }; }; // 绑定语言与字段对象的根类型 type Translations = { [key in Lang]: Fields; }; // 删掉任何一个条目都会报错,Translations类型确保不会遗漏任何字段 const translations: Translations = { de: { history: { locationChanged: "Standort geändert", manuallyCreated: "Manuell erstellt", }, orderManagement: { order: "Auftrag", }, }, en: { history: { locationChanged: "Location Changed", manuallyCreated: "Manually Created", }, orderManagement: { order: "Order", }, }, }; // TODO: 如何让这个函数更类型安全? export const getTranslations = (lang: Lang, context: string, field: string) => { return translations[lang][context][field]; }
解决方案:用泛型约束参数类型
不需要重构Fields类型,只需要给getTranslations函数添加泛型约束,让context和field只能取对应层级的合法键,同时让编辑器提供自动补全,编译期拦截无效参数。
修改后的getTranslations函数如下:
export const getTranslations = <C extends keyof Fields, F extends keyof Fields[C]>( lang: Lang, context: C, field: F ): Fields[C][F] => { return translations[lang][context][field]; }
说明:
C extends keyof Fields:约束context参数只能是Fields类型的键(也就是'history'或'orderManagement')F extends keyof Fields[C]:约束field参数只能是当前context对应的子对象的键(比如选'history'时,field只能是'historyEntry'、'locationChanged'或'manuallyCreated')- 返回值类型
Fields[C][F]会被TypeScript自动推导为对应翻译字符串的类型,同时编辑器会自动补全合法参数
效果验证:
- 合法调用:
getTranslations('de', 'history', 'locationChanged')—— 编辑器会自动补全参数,编译正常 - 非法调用:
getTranslations('de', 'bar', 'baz')—— 编译期直接报错,提示'bar'不是Fields的合法键,'baz'也不是对应上下文的合法键
内容的提问来源于stack exchange,提问作者Tim Hilt
相关产品推荐
相关产品推荐

