MST

星途 面试题库

面试题:TypeScript 泛型在复杂数据结构封装中的深度应用

假设你需要封装一个通用的树形数据结构,节点可以包含不同类型的数据,并且要有添加节点、删除节点等方法。请使用 TypeScript 泛型来实现这个树形结构,并解释泛型在其中如何提高代码的可复用性和类型安全性。
31.1万 热度难度
前端开发TypeScript

知识考点

AI 面试

面试题答案

一键面试
class TreeNode<T> {
    data: T;
    children: TreeNode<T>[];

    constructor(data: T) {
        this.data = data;
        this.children = [];
    }

    addChild(child: TreeNode<T>) {
        this.children.push(child);
    }

    removeChild(childToRemove: TreeNode<T>) {
        this.children = this.children.filter(child => child!== childToRemove);
    }
}

class Tree<T> {
    root: TreeNode<T> | null;

    constructor() {
        this.root = null;
    }

    setRoot(data: T) {
        this.root = new TreeNode(data);
    }

    addNode(parentData: T, childData: T) {
        if (!this.root) {
            throw new Error('Tree has no root');
        }

        const queue: TreeNode<T>[] = [this.root];
        while (queue.length > 0) {
            const current = queue.shift()!;
            if (current.data === parentData) {
                const newChild = new TreeNode(childData);
                current.addChild(newChild);
                return;
            }
            queue.push(...current.children);
        }

        throw new Error('Parent node not found');
    }

    removeNode(nodeData: T) {
        if (!this.root) {
            throw new Error('Tree has no root');
        }

        const queue: TreeNode<T>[] = [this.root];
        const parents: TreeNode<T>[] = [null as unknown as TreeNode<T>];
        while (queue.length > 0) {
            const current = queue.shift()!;
            const parent = parents.shift()!;

            if (current.data === nodeData) {
                if (parent) {
                    parent.removeChild(current);
                } else {
                    this.root = null;
                }
                return;
            }

            queue.push(...current.children);
            parents.push(...new Array(current.children.length).fill(current));
        }

        throw new Error('Node not found');
    }
}

泛型在其中提高代码可复用性和类型安全性的解释

  1. 可复用性
    • 通过使用泛型 T,我们可以创建适用于不同数据类型的树形结构。例如,我们可以创建一个 Tree<number> 用于管理数字类型的数据节点,也可以创建 Tree<string> 用于管理字符串类型的数据节点。这使得代码可以在多种场景下复用,而不需要为每种数据类型都编写一套独立的树形结构代码。
  2. 类型安全性
    • 在编译阶段,TypeScript 基于泛型 T 进行类型检查。比如,当我们创建 Tree<number> 时,编译器会确保 addNode 方法中传入的 parentDatachildData 都是 number 类型。如果传入了其他类型,编译器会报错,这有助于在开发阶段发现类型相关的错误,提高代码的健壮性。