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

如何为带递归children属性的泛型树结构指定返回类型?

解决泛型树结构的递归类型定义问题

要实现保留原类型所有属性且支持任意层级嵌套的树结构,核心是通过递归泛型类型来描述节点结构。

步骤1:定义递归节点类型

创建一个泛型类型TreeNode<T>,它既包含原类型T的所有属性,又递归引用自身作为children的类型,以此支持无限层级嵌套:

type TreeNode<T> = T & {
  children: TreeNode<T>[];
};

步骤2:修改函数返回类型

将函数的返回类型指定为TreeNode<T>[],同时在构建节点时用类型断言确保类型匹配:

const items = [
  { id: 1, path: 'a', name: 'path1' },
  { id: 2, path: 'a,b', name: 'path2' },
  { id: 3, path: 'a,b,c', name: 'path3' },
];

interface Example {
  id: number;
  path: string;
}

type TreeNode<T> = T & {
  children: TreeNode<T>[];
};

export function test<T extends Example>(items: T[]): TreeNode<T>[] {
  // 示例树构建逻辑(可根据实际path规则优化)
  const tree: TreeNode<T>[] = [];
  
  // 构建根节点
  const root = items.find(item => item.path.split(',').length === 1);
  if (root) {
    const rootNode = { ...root, children: [] } as TreeNode<T>;
    tree.push(rootNode);
    
    // 构建子节点
    const children = items.filter(item => item.path.startsWith(root.path + ','));
    children.forEach(child => {
      const childNode = { ...child, children: [] } as TreeNode<T>;
      // 递归添加更深层级节点(此处简化处理,实际可通过递归函数实现)
      const grandChildren = items.filter(item => item.path.startsWith(child.path + ','));
      grandChildren.forEach(grandChild => {
        childNode.children.push({ ...grandChild, children: [] } as TreeNode<T>);
      });
      rootNode.children.push(childNode);
    });
  }
  
  return tree;
}

为什么之前的尝试不生效?

你之前使用的(T & {children: T})[]存在本质问题:children的类型是T,而T本身并不包含children属性,因此只能支持一级嵌套。而递归的TreeNode<T>让children的类型也是TreeNode<T>,每个子节点都自带children属性,自然支持任意层级的嵌套结构。

类型验证

调用函数后,TypeScript会正确推断所有层级的属性,类型提示完全生效:

const result = test(items);
// 可正常访问任意层级的属性,类型系统会自动识别
console.log(result[0].children[0].children[0].name); // 类型为string

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 04:20:05