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

如何结合字符串字面量类型实现TypeScript函数重载并匹配返回类型?

如何让TypeScript函数根据联合类型参数返回对应类型?

我定义了字符串字面量联合类型:

export type FooMedia = "course" | "article" | "podcast";

接着写了重载的getFoo函数,根据传入的不同类型返回对应的数据结构:

function getFoo(
  id: string,
  type: "article"
): Promise<AxiosResponse<Article, any>>;

function getFoo(
  id: string,
  type: "podcast"
): Promise<AxiosResponse<Podcast, any>>;

function getFoo(
  id: string,
  type: "course"
): Promise<AxiosResponse<Course, any>>;

function getFoo<T extends FooMedia, R extends Media>(id: string, type: T) {
  const endpoint = `/api/${type}/${id}`;
  return axios.get<R>(endpoint);
}

但当用FooMedia类型的变量调用getFoo时,出现类型错误:FooMedia无法赋值给"article"/"podcast"/"course"类型参数:

function bar(type: FooMedia) {
  return getFoo("t", type); // 类型错误
}

想实现的效果是:根据传入的FooMedia类型参数,自动推导对应的返回类型,这是否可行?


问题原因

函数重载的每个签名仅匹配单个字面量类型,而FooMedia是三个字面量的联合类型。当传入联合类型变量时,TypeScript无法确定它具体对应哪个重载分支,因此抛出类型不匹配的错误。

可行解决方案:用泛型+类型映射替代重载

通过定义一个类型映射表,将每个FooMedia成员与对应的返回类型关联,再用泛型约束实现自动推导:

  1. 先定义类型映射关系:
// 假设Article、Podcast、Course是已定义的业务类型
type MediaResponseMap = {
  article: Promise<AxiosResponse<Article, any>>;
  podcast: Promise<AxiosResponse<Podcast, any>>;
  course: Promise<AxiosResponse<Course, any>>;
};
  1. 改写getFoo函数,利用泛型和映射类型推导返回值:
function getFoo<T extends FooMedia>(id: string, type: T): MediaResponseMap[T] {
  const endpoint = `/api/${type}/${id}`;
  // 这里需要用类型断言,因为axios无法自动推导具体返回类型
  return axios.get(endpoint) as MediaResponseMap[T];
}
  1. 现在调用bar函数时,TypeScript会自动推导返回类型为对应分支的联合:
function bar(type: FooMedia) {
  return getFoo("t", type);
  // 返回类型为:Promise<AxiosResponse<Article, any>> | Promise<AxiosResponse<Podcast, any>> | Promise<AxiosResponse<Course, any>>
}

如果需要在调用时精确推导单个分支的类型,直接传入字面量即可:

const articleRes = getFoo("1", "article"); // 类型为Promise<AxiosResponse<Article, any>>

补充:保留重载的兼容写法

如果想保留原有重载,需要调整实现函数的签名,让它能兼容联合类型参数:

// 重载签名不变
function getFoo(
  id: string,
  type: "article"
): Promise<AxiosResponse<Article, any>>;

function getFoo(
  id: string,
  type: "podcast"
): Promise<AxiosResponse<Podcast, any>>;

function getFoo(
  id: string,
  type: "course"
): Promise<AxiosResponse<Course, any>>;

// 实现签名改为接受FooMedia联合类型,返回对应联合类型
function getFoo(id: string, type: FooMedia): Promise<AxiosResponse<Article | Podcast | Course, any>> {
  const endpoint = `/api/${type}/${id}`;
  return axios.get(endpoint);
}

不过这种写法的类型推导精度不如映射类型,返回值会是所有可能类型的联合,无法在调用时精确到单个分支。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 08:20:25