Typescript 树结构的接口定义

9

我想为树结构定义一个接口。

每个节点可以有零个或多个子节点:

export interface TreeNode {
  children?: Array<TreeNode>;
}

我已经为TreeNode实现了一个遍历函数。
export function traverseTree(treeData: Array<TreeNode> | TreeNode, callback: (treeNode: any) => any) {
  // implementation omitted
}

我想测试它。代码如下:

const treeData = [
  {
    name: "root_1",
    children: [
      {
        name: "child_1",
        children: [
          {
            name: "grandchild_1"
          },
          {
            name: "grandchild_2"
          }
        ]
      }
    ]
  },
  {
    name: "root_2",
    children: []
  }
];
const traversingHistory = [];
const callback = (treeNode: any) => {
  traversingHistory.push(treeNode.name);
}
traverseTree(treeData, callback);

然而,编译失败,因为treeData的类型参数不能应用于traverseTree
我不想在接口TreeNode中添加属性name,因为树节点可以具有动态属性。我该如何修改TreeNode接口以接受更通用的类型?
3个回答

14

您可能遇到的错误是:

对象字面量只能指定已知属性,并且“name”不存在于类型中

如果您想允许其他键,它必须成为类型的一部分。您可以使用索引签名来实现此目的:

export interface TreeNode {
  [key: string]: any // type for unknown keys.
  children?: TreeNode[] // type for a known property.
}

12

我认为使用 泛型 而不是 [key: string]: any 更适合:

export type Tree<T> = T & {
  children?: T[];
}

保留所需和可选字段的 Item 类型,我们要构建一棵树:Tree<Item>。 对于这个问题,Item 的格式为:{ name: string }

1

尝试使用此联合类型与object一起:

type TreeNode = {
    children?: Array<TreeNode>;
} & object;

1
Alex Wayne的回答更好。但作为一个变体。 - Mark Partola

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接