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

TypeScript中如何根据数组参数推断getItem函数的返回值类型?

问题描述

我正在使用一种API模式,调用getItem函数会返回一个包含少量属性的对象:

{ id: 123, isBig: true }

我还可以向getItem函数传入一个名为properties的数组参数,以请求额外属性。例如调用getItem({ properties: ['color'] })时,应返回{ id: 123, isBig: true, color: 'red' }。

我的Item类型将额外属性定义为可选属性:

type Item = { id: number, isBig: boolean, color?: string }

我希望为getItem函数添加类型定义,使得当传入{ properties: ['color'] }时,TypeScript能推断出返回值中的color属性必然存在。

我最初想到使用泛型,写法大致如下:

type APIFunction<TReturnType, TProperties extends (keyof TReturnType)[] =[]> = 
  (params: { properties: TProperties }) => // oops, what do we return here?

但这种方法需要遍历泛型TProperties数组,我不知道TypeScript是否支持该操作,请问这在TypeScript中可行吗?

解决方案

完全可行,TypeScript可以通过泛型结合数组字面量类型推断,再搭配Required、Pick这些内置工具类型实现这个需求。

具体实现步骤

  • 先定义好基础的Item类型,包含固定必填属性和可选的扩展属性
  • 给getItem函数声明泛型TProps,约束它是Item属性键组成的数组类型,用来捕获传入的properties数组的具体元素类型
  • 返回类型用交叉类型组合:基础Item类型 + 选中的扩展属性(转为必填)

完整代码示例

// 基础Item类型定义
type Item = {
  id: number;
  isBig: boolean;
  color?: string;
  size?: number;
};

// 带类型推断的getItem函数
function getItem<TProps extends Array<keyof Item>>(
  params?: { properties: TProps }
): Item & Required<Pick<Item, TProps[number]>> {
  // 模拟API返回逻辑,实际项目替换为真实接口调用
  const baseItem = { id: 123, isBig: true };
  const extraProps = params?.properties.reduce((acc, prop) => {
    // 模拟不同属性的返回值
    if (prop === 'color') acc[prop] = 'red';
    if (prop === 'size') acc[prop] = 42;
    return acc;
  }, {} as Record<TProps[number], unknown>);
  
  return { ...baseItem, ...extraProps } as Item & Required<Pick<Item, TProps[number]>>;
}

// 测试效果
const item1 = getItem();
// 类型:{ id: number; isBig: boolean; color?: string; size?: number; }

const item2 = getItem({ properties: ['color'] });
// 类型:{ id: number; isBig: boolean; color: string; size?: number; }

const item3 = getItem({ properties: ['color', 'size'] });
// 类型:{ id: number; isBig: boolean; color: string; size: number; }

核心逻辑说明

  • TProps[number]:从数组泛型中提取元素的联合类型,比如传入['color']时,TProps[number]就是'color'
  • Pick<Item, TProps[number]>:从Item类型中筛选出指定的属性
  • Required<...>:把筛选出的可选属性强制转为必填
  • 交叉类型Item & Required<...>:确保返回值既保留Item的所有属性,又让指定的扩展属性变为必填

这样TypeScript就能根据你传入的properties数组,自动推断返回值里哪些属性是必然存在的。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 10:52:40