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

TypeScript API封装:基于输入键实现精确返回类型推导

解决方案:让TypeScript精确推断API封装的返回类型

你的核心问题是传入键数组后,TypeScript无法精确识别返回数组中对象的可用属性——原代码里返回类型用typeof arg[number]会把所有传入的键合并成联合类型,导致TypeScript认为返回对象包含所有映射后的属性,而非仅你指定的那些。下面是修复后的实现:

完整代码

type someType = {
    statuses?: string[],
    distances?: number[] // 所有数组长度一致
}

type someOtherType = {
  status?: string,
  distance?: number
}

// 定义键映射关系,用as const让TypeScript保留字面量类型
const Mapping = {
  statuses: "status",
  distances: "distance"
} as const;

// 从Mapping中提取类型:someType的键对应到someOtherType的键
type KeyMapping = typeof Mapping;
type SomeTypeKey = keyof someType;
type MappedKey<K extends SomeTypeKey> = KeyMapping[K];

// 定义元组到对象类型的映射:遍历传入的键元组,生成仅包含对应映射属性的对象
type MapKeysToMapped<T extends readonly SomeTypeKey[]> = {
  [K in T[number]]-?: someOtherType[MappedKey<K>]
};

function a<T extends readonly SomeTypeKey[]>(arg: T): MapKeysToMapped<T>[] {
  // 模拟API响应,确保类型是仅包含传入键的Required someType
  const someResponseObj = {
    statuses: ["active", "inactive"],
    distances: [100, 200]
  } as Required<Pick<someType, T[number]>>;

  // 获取数组长度(取第一个非空数组的长度,因为所有数组长度一致)
  const arrLength = Object.values(someResponseObj)[0]?.length ?? 0;
  const result: MapKeysToMapped<T>[] = [];

  for (let i = 0; i < arrLength; i++) {
    // 构建每个对象,reduce时确保类型正确
    const mappedObj = arg.reduce((agg, key) => {
      const mappedKey = Mapping[key];
      agg[mappedKey as keyof MapKeysToMapped<T>] = someResponseObj[key][i];
      return agg;
    }, {} as MapKeysToMapped<T>);

    result.push(mappedObj);
  }

  return result;
}

// 测试效果
const b = a(["statuses"]);
b[0].status; // ✅ 类型正确:string
// b[0].distance; ❌ TypeScript会报错:属性'distance'不存在于类型'{ status: string; }'

const c = a(["statuses", "distances"]);
c[0].status; // ✅ string
c[0].distance; // ✅ number

关键修改点

  1. 固定映射类型:把Mapping用as const声明,让TypeScript保留每个键的字面量类型,而不是宽泛的keyof someOtherType。
  2. 元组遍历映射:MapKeysToMapped<T>类型遍历传入的键元组T,生成仅包含对应映射属性的对象类型,而非合并所有可能的属性。
  3. 精确泛型约束:函数泛型T extends readonly SomeTypeKey[]确保传入的是键的元组而非数组,保留每个元素的具体类型。
  4. 类型安全的reduce:初始化agg为MapKeysToMapped<T>类型,避免不必要的类型断言,同时确保每个赋值的键都符合目标类型。

这样修改后,TypeScript就能完全根据你传入的键数组,精确推断返回数组中每个对象的可用属性,实现你需要的类型提示和校验。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 13:18:09