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

如何让TypeScript函数接收泛型输入并返回同键异值类型对象

解决方案:精确映射A的子集到B的对应子集

问题核心

你遇到的核心问题是泛型约束不够严格:T extends A允许T包含A以外的额外属性,导致TypeScript无法确定keyof T的所有键都存在于B中。而Partial<A>的问题在于返回类型无法精确匹配传入的属性集合,只能返回所有属性可选的类型。

正确实现方式

我们需要将泛型T约束为仅包含A的属性子集,让TypeScript明确keyof T的每个键都同时存在于A和B中。以下是两种可行方案:

方案一:子集泛型约束

type A = {
  foo: number
  bar: number
}

type B = {
  foo: string
  bar: string
}

function f<T extends Pick<A, keyof T>>(input: T): { [K in keyof T]: B[K] } {
  const res = {} as { [K in keyof T]: B[K] };
  // 示例实现:将数字转为字符串
  for (const key in input) {
    res[key] = input[key].toString();
  }
  return res;
}

方案二:键集泛型约束

如果你希望更明确地指定传入的键范围,可以直接约束键的集合:

function f<K extends keyof A>(input: Pick<A, K>): Pick<B, K> {
  const res = {} as Pick<B, K>;
  for (const key in input) {
    res[key] = input[key].toString();
  }
  return res;
}

效果验证

两种方案都能实现你想要的精确类型推断:

const a = f({});          // 类型:{}
const b = f({foo: 1});    // 类型:{foo: string}
const c = f({bar: 2});    // 类型:{bar: string}
const d = f({foo:1, bar:2}); // 类型:{foo: string, bar: string}

原理说明

  • Pick<A, keyof T>:确保T的所有键都来自A,排除了额外属性的可能性,让TypeScript确认keyof T的每个键都能索引B。
  • { [K in keyof T]: B[K] }:遍历T的所有键,将对应的值类型替换为B中同键的类型,实现精确映射。
  • 方案二中的Pick<B, K>是上述映射类型的简写,效果完全一致。

简化技巧(可选)

如果A和B结构高度相似(仅值类型不同),可以定义通用映射类型来简化代码:

type MapToB<T extends Partial<A>> = { [K in keyof T]: B[K] };

function f<T extends Pick<A, keyof T>>(input: T): MapToB<T> {
  // 实现代码同上
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 02:56:52