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

TypeScript无法正确推断字典类型?如何优化类型推断?

TypeScript翻译函数类型推断问题解答

问题代码

export type Locale = "en" | "fr";
export type Namespace = "products" | "home";

const dict = {
  en: {
    home: { title: "My Super Title" },
    products: { product: "Product" },
  },
  fr: {
    home: { title: "Mon Super Titre" },
    products: { product: "Produit" },
  },
};

export const getTranslation = (namespace: Namespace, locale: Locale) => {
  return dict[locale][namespace];
};

const t = getTranslation("home", "en");
// TypeScript推断的t类型
// const t: {
//   title: string;
// } | {
//   product: string;
// } | {
//   title: string;
// } | {
//   product: string;
// }

核心问题

  • 为什么TypeScript无法正确推断该类型?
  • 能否通过给getTranslation添加手动类型标注,让它正确推断出具体类型?

期望推断类型:

{
    title: string;
}

解答

1. 类型推断错误的原因

TypeScript默认会将getTranslation的返回值推断为所有dict[Locale][Namespace]组合的联合类型,因为函数的两个参数namespace和locale是独立的联合类型——TS无法自动建立“传入特定locale+namespace时,返回对应具体子对象”的关联关系,只能把所有可能的取值结果合并,最终形成重复的联合类型。

2. 手动类型标注的解决方案

利用TypeScript 5+的泛型特性,通过泛型参数绑定传入的locale和namespace的具体字面量类型,让TS精准关联到对应返回值的类型。

方案1:保留字面量类型的精准推断

export type Locale = "en" | "fr";
export type Namespace = "products" | "home";

// 用as const锁定对象的字面量类型,避免TS自动拓宽为string
const dict = {
  en: {
    home: { title: "My Super Title" },
    products: { product: "Product" },
  },
  fr: {
    home: { title: "Mon Super Titre" },
    products: { product: "Produit" },
  },
} as const;

// 泛型L和N分别约束为Locale和Namespace的子集,绑定参数的具体类型
export const getTranslation = <L extends Locale, N extends Namespace>(namespace: N, locale: L) => {
  return dict[locale][namespace];
};

const t = getTranslation("home", "en");
// 推断类型:{ readonly title: "My Super Title" }

方案2:统一返回宽松的string类型

如果不需要保留字面量,只需要属性值为string的类型,可以手动定义翻译类型并标注返回值:

export type Locale = "en" | "fr";
export type Namespace = "products" | "home";

const dict = {
  en: {
    home: { title: "My Super Title" },
    products: { product: "Product" },
  },
  fr: {
    home: { title: "Mon Super Titre" },
    products: { product: "Produit" },
  },
};

// 定义通用翻译类型,提取对应locale+namespace的结构并将值统一为string
type Translation<L extends Locale, N extends Namespace> = {
  [K in keyof typeof dict[L][N]]: string;
};

export const getTranslation = <L extends Locale, N extends Namespace>(
  namespace: N, 
  locale: L
): Translation<L, N> => {
  return dict[locale][namespace] as Translation<L, N>;
};

const t = getTranslation("home", "en");
// 推断类型:{ title: string }

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 22:48:09