如何更简洁地将层级对象映射为可递归迭代的类型化Item树结构?
问题描述
现有如下嵌套层级的数据对象:
const data = { id: "parent", children: { child0: { id: "child0", children: { grandchild0: { id: "grandchild0", children: {} } } }, child1: { id: "child1", children: {} } } }
需要将其转换为如下可递归迭代的类型化树结构:
type Item = { id:string, children?: Item[], }
我已经通过递归循环遍历的方式实现了转换(代码如下),但想知道有没有更简洁优雅的实现方案?
function dataToItem(data: any):Item { let item:Item = { id: '', children: [] } const keys = Object.keys(data); for (const key of keys) { const value = data[key]; switch (key) { case 'id': item.id = value; break; case 'children': item.children = []; const children = Object.values(value); for (const child of children) { const childItem = dataToItem(child); item.children.push(childItem); } } } return item; } const item:Item = dataToItem(data); console.log(item);
简洁实现方案
方案一:递归解构式转换
利用对象解构和递归特性,直接构建目标结构,代码更紧凑直观:
function transformData(data: any): Item { const { id, children = {} } = data; return { id, children: Object.values(children).map(child => transformData(child)) }; }
直接解构出id和children(默认空对象避免报错),用Object.values把children的键值对转为数组,再递归映射每个子节点即可。
方案二:箭头函数极简版
用箭头函数和空值合并运算符进一步简化,逻辑更凝练:
const transformData = (data: any): Item => ({ id: data.id, children: Object.values(data.children ?? {}).map(transformData) });
data.children ?? {}确保当原数据没有children字段时,用空对象兜底,避免Object.values执行报错。
方案三:类型安全增强版
如果需要更严格的类型检查,可以先定义输入数据的类型,让TypeScript在编译阶段就校验结构:
type RawNode = { id: string; children: Record<string, RawNode>; }; function transformData(data: RawNode): Item { return { id: data.id, children: Object.values(data.children).map(transformData) }; }
这样能提前发现输入数据的结构错误,避免运行时问题。
这些方案都去掉了原代码中冗余的循环和switch判断,利用函数式编程的特性让逻辑更清晰,代码量大幅减少。
内容的提问来源于stack exchange,提问作者Cambiata
相关产品推荐
相关产品推荐

