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

如何编写TypeScript函数,基于判别器映射两个联合类型?

基于判别器的联合类型映射函数实现

当然可以实现这个需求!TypeScript的条件类型和联合类型的判别特性,正好能帮我们编写一个能自动推断输出类型的map函数签名——让编译器根据输入的判别器字段,精准匹配对应的输出类型。

基础场景实现

先从你给出的In/Out联合类型示例入手,我们先定义一个映射辅助类型,用来关联输入和输出的判别器:

// 输入联合类型
type InA = { type: 'a', data: string };
type InB = { type: 'b', data: number };
type In = InA | InB;

// 输出联合类型
type OutA = { type: 'a', data: Object };
type OutB = { type: 'b', data: Array<number> };
type Out = OutA | OutB;

// 辅助类型:根据输入的type字段,匹配对应的输出类型
type MapInToOut<T extends In> = T extends { type: infer U } 
  ? Extract<Out, { type: U }> 
  : never;

接着给map函数加上这个泛型约束,就能实现自动类型推断:

function map<T extends In>(input: T): MapInToOut<T> {
  // 根据判别器编写转换逻辑
  switch (input.type) {
    case 'a':
      return { type: 'a', data: {} } as MapInToOut<T>;
    case 'b':
      return { type: 'b', data: [input.data] } as MapInToOut<T>;
    default:
      throw new Error('Unknown type');
  }
}

// 使用示例:编译器自动推断返回值为OutB
const result = map({ type: 'b', data: 999 });
// result的类型将被自动推导为 { type: 'b', data: number[] }

你的实际场景优化版

你基于@titian-cernicova-dragomir答案修改的实现已经非常贴合业务场景了,我们再把它梳理得更清晰:

/** Http Request types **/
type RequestA = { type: 'names', url: '/names' };
type RequestB = { type: 'numbers', url: '/numbers' };
type Request = RequestA | RequestB;

/** Response types **/
type ResponseA = { type: 'names', data: Array<string> };
type ResponseB = { type: 'numbers', data: Array<number> };
type Response = ResponseA | ResponseB;

/** 辅助类型:根据请求的type字段,匹配对应的响应类型 */
type GetResponse<T extends Request> = T extends { type: infer U } 
  ? Extract<Response, { type: U }> 
  : never;

然后编写泛型的fetchData函数,利用辅助类型自动推断返回的Promise类型:

export function fetchData<T extends Request>(request: T): Promise<GetResponse<T>> {
  return fetch(request.url)
    .then(response => response.json())
    .then(data => {
      return { type: request.type, data } as GetResponse<T>;
    });
}

// 使用场景:编译器自动识别返回类型
const names = fetchData({ type: 'names', url: '/names' });
// names的类型是 Promise<ResponseA>(即 Promise<{ type: 'names', data: string[] }>)

const numbers = fetchData({ type: 'numbers', url: '/numbers' });
// numbers的类型是 Promise<ResponseB>(即 Promise<{ type: 'numbers', data: number[] }>)

这个实现的核心逻辑是:用infer关键字提取输入类型的type字段值,再通过Extract工具类型从输出联合类型中筛选出匹配的类型,完美实现了基于判别器的类型映射与自动推断。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 07:30:06