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

如何用TypeScript为数组生成的对象定义返回类型?

为数组转对象的函数定义TypeScript返回类型

需求描述

需要实现一个TypeScript函数,接收一组包含id属性的对象数组(id的取值来自指定联合类型),返回以这些id为属性名的对象。要求TypeScript能准确推断返回对象的可用属性——即只有传入数组中出现过的id才会被识别为有效属性。

示例代码(原需求)

type Names = "input" | "button" | "form";
type FuncParam = { id: Names };
type FuncReturnType = ??????;

/*
 * 将包含id的对象数组转换为:以id为属性名、值为"hello"的对象
*/
const defineSomethings = (somethings: FuncParam[]) => {
  const obj = {} as FuncReturnType; // 初始化返回对象
  somethings.map(({ id }) => obj[id] = "hello"); // 填充属性
  return obj;
};

const A = defineSomethings(
  { id: "input" },
  { id: "form" }
);

const B = defineSomethings(
  { id: "button" }
);

// 期望的类型检查结果
A.input // ✅ 正常识别
A.form // ✅ 正常识别
A.button // ❌ 报错,A无此属性

B.input // ❌ 报错
B.form // ❌ 报错
B.button // ✅ 正常识别

解决方案

核心是用泛型捕获传入数组的具体id字面量类型,而非依赖固定联合类型,让TypeScript精准推断返回对象的属性。修改后的代码如下:

type Names = "input" | "button" | "form";
type FuncParam = { id: Names };

// 用泛型T捕获传入数组的具体元素类型
const defineSomethings = <T extends FuncParam[]>(somethings: [...T]) => {
  // 返回对象的类型:以数组中所有id为属性名,值为string类型
  const obj = {} as Record<T[number]['id'], string>;
  // 遍历赋值(用forEach替代map更合理,因为不需要返回新数组)
  somethings.forEach(({ id }) => obj[id] = "hello");
  return obj;
};

// 调用时传入数组(修正原代码参数写法错误)
const A = defineSomethings([
  { id: "input" },
  { id: "form" }
]);

const B = defineSomethings([
  { id: "button" }
]);

// 类型检查符合预期
A.input; // ✅
A.form; // ✅
A.button; // ❌ 类型错误:类型“Record<"input" | "form", string>”上不存在属性“button”

B.input; // ❌ 类型错误
B.form; // ❌ 类型错误
B.button; // ✅

关键细节说明

  1. 泛型约束与元组推断:T extends FuncParam[]确保传入数组元素符合FuncParam结构,[...T]是元组语法,让TypeScript捕获数组中每个元素的具体id字面量类型(而非笼统推断为FuncParam[])。
  2. 返回类型推导:T[number]['id']提取数组中所有元素的id,组成精准的字面量联合类型(比如A对应的是"input" | "form"),再通过Record<K, V>工具类型定义返回对象结构——属性名为该联合类型,属性值为string。
  3. 类型断言初始化:用as Record<T[number]['id'], string>告知TypeScript初始化的空对象最终会被填充为指定结构,避免类型报错。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 18:04:50