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

TypeScript中如何从判别式联合回调推断映射的返回类型

TypeScript中如何从判别式联合回调推断映射的返回类型

嘿,这个需求我之前折腾过好一阵!咱们直接用你给的例子来一步步拆解,很快就能搞懂怎么实现~

首先,你现在有这么一个函数:

function createRecord(createValue: (input: 'a' | 'b') => unknown): Record<'a' | 'b', unknown> {
  // 这里是函数的基础实现,比如遍历生成对应记录
  return {
    a: createValue('a'),
    b: createValue('b')
  } as Record<'a' | 'b', unknown>;
}

但你希望调用的时候,传入带条件类型的泛型回调后,TypeScript能自动推断出返回的x类型是{ a: 'A', b: 'B' },而不是现在这种宽泛的Record<'a' | 'b', unknown>,就像你写的这段调用代码:

const x = createRecord(<Input extends 'a' | 'b'>(input: Input): Input extends 'a' ? 'A' : 'B' => {
  return input === 'a' ? 'A' : 'B';
});

那问题出在哪呢?原来的createRecord函数签名太“死板”了,它没办法识别到回调里的条件类型是和每个输入键一一对应的,只能返回最宽泛的unknown值类型。

要解决这个问题,我们需要把createRecord改成泛型函数,让它能关联输入的联合类型和回调的返回类型,具体写法如下:

// 泛型函数签名,让TypeScript能精准推断映射关系
function createRecord<K extends string | number | symbol>(
  createValue: <Key extends K>(key: Key) => unknown
): { [P in K]: ReturnType<(typeof createValue) extends (k: P) => infer R ? R : never> };

// 函数实现部分,用类型断言绕开TypeScript的推断限制
function createRecord<K extends string | number | symbol>(
  createValue: (key: K) => unknown
) {
  const result = {} as Record<K, unknown>;
  // 这里需要拿到K对应的所有键,比如K是字面量联合时,可以手动传入或用类型工具提取
  const keys = ['a', 'b'] as K[];
  for (const key of keys) {
    result[key] = createValue(key);
  }
  return result;
}

现在再调用这个函数,TypeScript就能准确推断出x的类型啦:

const x = createRecord(<Input extends 'a' | 'b'>(input: Input): Input extends 'a' ? 'A' : 'B' => {
  return input === 'a' ? 'A' : 'B';
});

// 此时x的类型会被正确推断为 { a: 'A', b: 'B' }

核心逻辑其实就是:把原来固定的Record<'a' | 'b', unknown>换成泛型映射类型,让TypeScript能把回调里每个输入键对应的返回类型,一一映射到最终返回对象的每个属性上,这样就能从判别式联合的回调里自动推断出精准的返回类型了。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.08 13:44:32