TypeScript 如何做树形结构类型

在日常开发中,我们常常用树形结构来组织数据,比如侧边栏菜单、文件目录、部门架构。用 JavaScript 写这类数据很简单,但如果想让代码更安全、少出 Bug,TypeScript 的类型系统就能派上大用场。很多人觉得 TypeScript 做树形结构类型很复杂,其实只要结合生活里的“家族树”例子,就能轻松理解。

先搞懂树形结构的核心

不管是菜单还是文件树,树形结构的本质都是“父节点带子节点”。比如一家公司的部门,总公司是父节点,下面分人事部、技术部,技术部又分前端组、后端组,每个部门都可能有自己的下属部门——这就是典型的“递归结构”。

TypeScript 如何做树形结构类型

如果用 JavaScript 写这个数据,大概是这样的:

`javascript

const company = {

name: "总公司",

children: [

{ name: "人事部", children: [] },

{

name: "技术部",

children: [

{ name: "前端组", children: [] },

{ name: "后端组", children: [] }

]

}

]

};

`

但如果没人规范这个结构,有人误加了age: 25这种多余属性,或者把children写成字符串,代码跑起来很容易出问题。这时 TypeScript 的类型就能“管住”这些细节。

写一个基础的树形类型

第一步,先定义最核心的节点类型。每个节点必须有name(用来区分节点),还要有children(子节点列表),而且children可以是空数组(比如人事部没有下属)。

用 TypeScript 写就是:

`typescript

type TreeNode = {

name: string;

children: TreeNode[]; // 子节点也是TreeNode类型,这就是递归的关键

};

`

这个类型就像一张“模板”:所有树形节点都必须有name属性,且children只能是TreeNode组成的数组。用它规范之前的公司数据,就变成:

`typescript

const company: TreeNode = {

name: "总公司",

children: [

{ name: "人事部", children: [] },

{

name: "技术部",

children: [

{ name: "前端组", children: [] },

{ name: "后端组", children: [] }

]

}

]

};

`

现在如果给某个节点加age,TypeScript 会直接报错,帮我们提前发现问题。

给树形结构加“专属属性”

有时候不同类型的节点需要不同属性,比如文件树里,文件夹有isFolder,文件有fileSize。这时候可以给基础类型加“扩展”,让类型更灵活。

比如定义FileNode和FolderNode,再用联合类型把它们合并成FileTree:

`typescript

// 文件节点,有大小属性

type FileNode = {

name: string;

isFolder: false;

fileSize: number;

children?: never; // 文件没有子节点,所以children是可选且不能有

};

// 文件夹节点,没有大小但有子节点

type FolderNode = {

name: string;

isFolder: true;

fileSize?: never;

children: FileTree[]; // 子节点可以是文件或文件夹

};

// 最终的树形类型,要么是文件要么是文件夹

type FileTree = FileNode | FolderNode;

`

用这个类型规范文件数据,既保证了结构正确,又能区分节点类型——比如你写file.fileSize时,TypeScript 会自动知道这是文件的属性,不会让你去问文件夹要fileSize。

避免常见的坑

很多人写树形类型时会犯两个错:一是把children设成可选,结果有人写了children: undefined,反而出问题;二是没限制递归,导致类型无限套娃。其实只要记住两个小技巧:第一,children如果是必须的,就直接写children: 具体类型[],如果是可选的,就加?但要在逻辑里处理空的情况;第二,递归类型必须“有出口”,比如children是空数组时就不会继续嵌套,不会爆类型错误。

掌握了这些,不管是菜单、文件树还是部门架构,都能用 TypeScript 写出安全又清晰的树形结构类型,再也不用担心数据结构乱掉了。

上一篇 C / C++ 编程语言核心特性与应用场景的入门知识科普