You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为拼接参数的getLocale函数实现TypeScript类型检查?

解决方案

问题核心是当前类型约束错误地把key直接当作data的键,但实际data的键是key+_+locale的组合。我们可以通过模板字符串类型和泛型约束,让TypeScript正确关联key、locale与data的键结构:

const allowedLangs = ['nl', 'en'] as const;
type AllowedLang = typeof allowedLangs[number];

// 提取data中所有去掉语言后缀后的基础键
type BaseKeys<T> = {
  [K in keyof T]: K extends `${infer Base}_${AllowedLang}` ? Base : never;
}[keyof T];

function getLocale<
  T extends Record<`${B}_en`, any>, // 强制保证回退语言en的键存在
  B extends BaseKeys<T>,
  L extends AllowedLang
>(
  data: T,
  key: B,
  locale: L
): T[`${B}_${L}`] | T[`${B}_en`] | 'not-found' {
  // 用as keyof T做类型断言,辅助TS识别组合后的键属于data
  return data[`${key}_${locale}` as keyof T] ?? data[`${key}_en` as keyof T] ?? 'not-found';
}

// 测试用例
const data = {
  name_nl: 'Naam',
  name_en: 'Name',
  age_en: 'Age' // 仅包含回退语言的键
};

// 合法调用
getLocale(data, 'name', 'nl'); // 返回'Naam'
getLocale(data, 'age', 'nl'); // 回退到age_en,返回'Age'
getLocale(data, 'name', 'en'); // 返回'Name'

// 非法调用会触发TS报错
// getLocale(data, 'invalidKey', 'nl'); // 错误:invalidKey不是合法基础键
// getLocale(data, 'age', 'fr'); // 错误:fr不在允许的语言列表中

关键细节说明

  • BaseKeys类型:遍历data的所有键,通过模板字符串类型提取去掉_语言后缀的基础键(比如从name_nl提取name),让key参数被严格约束为这些合法基础键。
  • 泛型约束T:要求data必须包含${key}_en的键,确保回退逻辑总有值可用;如果业务要求每个基础键必须有所有语言的对应键,可以去掉Partial,改为强制约束T extends Record<${B}_${L}, any> & Record<${B}_en, any>。
  • 空值合并运算符??:替换原代码的||,避免因值为假值(如空字符串、0)错误触发回退,更贴合“键不存在才回退”的逻辑。
  • 类型断言:由于TypeScript暂时无法自动推断${key}_${locale}是data的键,用as keyof T辅助类型检查,而泛型约束已经保证了该键要么存在,要么回退键一定存在。

内容的提问来源于stack exchange,提问作者Duncan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 08:27:36