MST

星途 面试题库

面试题:TypeScript类型推断之高级难度题

假设有一个复杂的嵌套对象结构,例如一个表示树状结构的对象,每个节点有子节点数组和其他属性。请说明如何利用TypeScript的类型推断来准确地定义该对象的类型,并且在添加新节点或访问节点属性时能获得正确的类型提示,同时描述类型推断在处理递归类型定义时的要点。
17.0万 热度难度
前端开发TypeScript

知识考点

AI 面试

面试题答案

一键面试
  1. 定义树状结构对象类型
    • 假设树状结构节点有 id(唯一标识)、name(节点名称)和 children(子节点数组)属性。可以这样定义类型:
interface TreeNode {
    id: number;
    name: string;
    children: TreeNode[];
}
  • 这样就定义了一个递归类型,TreeNode 类型的 children 数组元素又是 TreeNode 类型。
  1. 添加新节点与访问节点属性的类型提示
    • 添加新节点
function addChild(parent: TreeNode, newChild: TreeNode) {
    parent.children.push(newChild);
    return parent;
}
// 调用函数时会有正确的类型提示
let root: TreeNode = { id: 1, name: 'Root', children: [] };
let newNode: TreeNode = { id: 2, name: 'Child', children: [] };
addChild(root, newNode);
  • 访问节点属性
function printNodeName(node: TreeNode) {
    console.log(node.name);
}
printNodeName(root);
// 这里访问 `node.name` 时会有正确的类型提示,因为 `node` 被推断为 `TreeNode` 类型
  1. 类型推断在处理递归类型定义时的要点
    • 递归边界:递归类型定义必须有明确的边界,否则会导致类型检查无限循环。例如在上述 TreeNode 类型中,虽然 childrenTreeNode[],但数组最终会有尽头,不存在无限制的嵌套。
    • 使用接口:使用接口(interface)来定义递归类型是一种常见且清晰的方式。接口可以重复声明扩展,方便在不同地方对递归类型进行补充定义。
    • 类型别名:也可以使用类型别名(type)来定义递归类型,例如 type TreeNode = { id: number; name: string; children: TreeNode[] };,但在某些复杂场景下,接口的扩展性可能更有优势。
    • 类型检查工具:依赖 TypeScript 的类型检查机制,在编译时确保递归类型的使用符合定义,防止错误的类型赋值和操作。