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

如何利用TypeScript泛型扩展函数返回值类型并添加新属性?

解决TypeScript泛型添加属性后的类型定义问题

你的问题核心是返回类型没有包含新增的children属性——原函数返回Array<T>,但T(继承自Src)并没有children字段,所以TypeScript无法推断出返回值有这个属性。

要解决这个问题,你需要:

  1. 定义一个交叉类型,把原输入类型T和带有children的类型合并
  2. 修改函数的返回类型为这个交叉类型的数组
  3. 在函数内部赋值时,通过类型断言告诉TypeScript当前元素可以添加children属性

具体实现代码

// src array
const src = [
  { id: 3, parentId: 2 },
  { id: 2, parentId: 1 },
  { id: 1 },
  { id: 4 },
  { id: 5, parentId: 4 },
  { id: 6, parentId: 8 },
  { id: 7, parentId: 9 },
  { id: 7, parentId: 9, title: 'ssss' },
];

interface Src {
  id: number;
  parentId?: number | string;
  title?: string;
}

// 定义带children的交叉类型,这里假设children是同类型的节点数组(适合树形结构)
type NodeWithChildren<T> = T & { children: NodeWithChildren<T>[] };

function addChildren<T extends Src>(arr: T[]): NodeWithChildren<T>[] {
  // 这里以构建树形结构为例,你可以替换成自己的children赋值逻辑
  return arr.map(item => ({
    ...item,
    // 筛选当前节点的子节点
    children: arr.filter(child => child.parentId === item.id)
  })) as NodeWithChildren<T>[];
}

// 调用后,res的每个元素都会保留原类型属性,同时拥有children字段
const res = addChildren(src);
// 此时TypeScript会提示res[0]有id、parentId、children等属性
console.log(res[0].children);

关键说明

  • 交叉类型NodeWithChildren<T>:通过T & { children: ... }将原类型的所有属性和新增的children属性合并,确保返回值的类型既保留原结构,又包含新属性。
  • 类型断言:在map返回时用as NodeWithChildren<T>[]告诉TypeScript,我们已经给每个元素添加了children,可以安全地将其视为交叉类型。
  • 如果你的children不是子节点数组,而是其他类型(比如单个对象),只需要修改NodeWithChildren里的children类型即可,比如{ children: YourChildrenType }。

直接修改原数组的写法

如果你不想创建新数组,而是直接修改原数组,代码如下:

function addChildrenDirectly<T extends Src>(arr: T[]): NodeWithChildren<T>[] {
  for (let i = 0; i < arr.length; i++) {
    // 类型断言允许我们给原对象添加children属性
    (arr[i] as NodeWithChildren<T>).children = arr.filter(child => child.parentId === arr[i].id);
  }
  return arr as NodeWithChildren<T>[];
}

内容的提问来源于stack exchange,提问作者Eric-Guo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 11:54:20