如何让TypeScript合并翻译对象后保留精确类型?
解决next-intl合并翻译后的类型精确化问题
问题背景
使用combineTranslations合并SiteTranslations、AuthFeatureTranslations等翻译模块后,返回值被限定为AbstractIntlMessages这个宽泛类型,丢失了各模块的具体结构信息,导致next-intl无法提供自动补全和类型校验功能。
重构方案
利用TypeScript泛型捕获每个输入翻译模块的具体类型,通过递归交叉类型推导合并后的精确返回类型,替代原有的宽泛类型约束。
具体实现
1. 定义翻译模块类型(示例)
// 站点翻译模块类型 type SiteTranslations = { Site: { title: string; subtitle: string; }; }; // 鉴权功能翻译模块类型 type AuthFeatureTranslations = { Auth: { login: string; logout: string; }; };
2. 重构combineTranslations函数
import { AbstractIntlMessages } from 'next-intl'; // 递归推导合并后的类型 type CombineTranslations<T extends AbstractIntlMessages[]> = T extends [infer First extends AbstractIntlMessages, ...infer Rest extends AbstractIntlMessages[]] ? First & CombineTranslations<Rest> : {}; // 类型安全的合并函数 function combineTranslations<T extends AbstractIntlMessages[]>( ...translations: T ): CombineTranslations<T> { return translations.reduce((acc, curr) => ({ ...acc, ...curr }), {}) as CombineTranslations<T>; }
3. 使用示例
// 具体翻译内容 const siteTranslations: SiteTranslations = { Site: { title: '首页', subtitle: '欢迎访问' } }; const authTranslations: AuthFeatureTranslations = { Auth: { login: '登录', logout: '退出' } }; // 合并后获得精确类型 const combinedTranslations = combineTranslations(siteTranslations, authTranslations); // 支持自动补全与类型校验 combinedTranslations.Site.title; // ✅ 正常提示 combinedTranslations.Auth.login; // ✅ 正常提示 combinedTranslations.Site.invalidKey; // ❌ 类型报错,符合预期
关键说明
- 泛型
CombineTranslations通过递归解构输入数组的类型,将每个翻译模块的类型进行交叉合并,最终得到包含所有模块结构的精确类型。 - 类型断言
as CombineTranslations<T>用于告诉TypeScript,reduce合并后的结果符合推导的精确类型(因为reduce的默认返回类型无法自动识别交叉合并后的结构)。 - 所有输入的翻译模块必须符合
AbstractIntlMessages约束,确保与next-intl的类型体系兼容。
内容的提问来源于stack exchange,提问作者Joseph
相关产品推荐
相关产品推荐

