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

如何让TypeScript泛型函数第二个泛型参数可选,无需手动指定?

问题描述

我有一组不相关的对象,需要编写一个泛型函数来获取它们的值。给定以下类型:

type Circle = {
  color: string,
  radius: number,
}

type Person = {
  name: string,
  age: number,
}

我希望能这样调用泛型函数:

getData<Circle>('circle-id', ['radius']) // 返回类型 { radius: number }

但目前实现的方案需要传入两个泛型参数,使用体验很差:

getData<Circle, ['radius']>('circle-id', ['radius'])

当前的实现代码如下:

const getData = <Node, T extends Array<keyof Node>>(
  nodeId: string,
  attributes: T
): { [K in T[number]]: Node[K] } => {
 // ...
}

请问如何优化该函数,避免手动指定第二个泛型参数?我知道柯里化可能可以解决,但我的场景要求getData返回可序列化对象。


解决方案

你可以通过调整泛型参数约束、利用TypeScript自动类型推导来优化,无需手动指定第二个泛型参数。核心思路是让第二个泛型参数代表目标类型的键联合类型,而非键数组类型,让TS从传入的参数自动推导具体值。

优化后的代码如下:

const getData = <Node, T extends keyof Node>(
  nodeId: string,
  attributes: readonly T[]
): Pick<Node, T> => {
  // 示例实现:替换为实际的数据源获取逻辑
  const rawData = {} as Node;
  return attributes.reduce((result, key) => {
    result[key] = rawData[key];
    return result;
  }, {} as Pick<Node, T>);
};

调用示例

现在可以按照预期方式调用,TS会自动推导第二个泛型参数:

// 返回类型为 { radius: number }
getData<Circle>('circle-id', ['radius']);

// 返回类型为 { name: string; age: number }
getData<Person>('person-id', ['name', 'age']);

关键说明

  1. 泛型参数调整:将T的约束改为keyof Node,让T代表单个键或键的联合类型,TS能从数组参数自动推导T的具体值。
  2. 返回类型简化:使用TS内置的Pick工具类型,直接从Node中选取指定属性集合,替代手动映射的类型定义,代码更简洁。
  3. readonly数组参数:用readonly T[]作为参数类型,既兼容普通数组传入,又能避免TS将数组字面量类型拓宽为string[],确保类型推导准确。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 20:22:42