如何实现基于对象键路径生成完整路由的简洁TypeScript函数?
实现路由路径构建函数
buildRoute 问题描述
现有一个代表网站路由树的对象r,结构如下:
const r = { HOME: "start", ACCOUNT: { HOME: "account", PROFILE: "profile", ADDRESSES: { HOME: "addresses", DETAIL: ":addressId", }, }, ESHOP: { HOME: "eshop", INVOICES: "invoices", ORDERS: { HOME: "orders", DETAIL: ":orderId", }, }, INVENTORY: { HOME: "warehouse", CATEGORIES: { HOME: "categories", CATEGORY: { HOME: ":categoryId", PRODUCTS: { HOME: "products", PRODUCT: ":productId", }, }, }, }, };
需要构建一个函数buildRoute,传入路由对象r和键路径字符串,返回对应的完整路由路径,示例如下:
buildRoute(r, "r.ACCOUNT.ADDRESSES.DETAIL") // 返回:"start/account/addresses/:addressId" buildRoute(r, "r.INVENTORY.CATEGORIES") // 返回:"start/warehouse/categories" buildRoute(r, "r.INVENTORY.CATEGORIES.CATEGORY.PRODUCTS.PRODUCT") // 返回:"start/warehouse/categories/:categoryId/products/:productId"
规则说明:
- 键路径字符串以
"r"开头,后续为层级键名 "HOME"是任意路径/子路径的固定键,用于获取当前层级的基础路径- 路径片段之间用斜杠
/连接,最后一个路由片段直接取对应键的值
TypeScript解决方案
1. 类型定义
先定义递归的路由节点类型,确保类型安全:
// 路由节点:要么是字符串路径,要么是包含HOME键的嵌套对象 type RouteNode = string | { HOME: string; [key: string]: RouteNode; };
2. 函数实现
通过解析键路径、遍历路由树收集路径片段,最终拼接成完整路由:
function buildRoute(root: RouteNode, pathStr: string): string { // 解析路径字符串:移除开头的"r.",拆分为键数组 const keys = pathStr.replace(/^r\./, "").split("."); if (keys.length === 0) return ""; const pathSegments: string[] = []; let currentNode: RouteNode = root; // 先添加根节点的HOME路径 if (typeof currentNode !== "string") { pathSegments.push(currentNode.HOME); } // 遍历所有层级键 for (let i = 0; i < keys.length; i++) { const key = keys[i]; if (typeof currentNode === "string") break; const nextNode = currentNode[key]; if (!nextNode) throw new Error(`路由树中不存在键 ${key}`); // 最后一个键直接取对应值;非最后一个键取节点的HOME if (i === keys.length - 1) { pathSegments.push(typeof nextNode === "string" ? nextNode : nextNode.HOME); } else { if (typeof nextNode === "string") { throw new Error(`键 ${key} 对应字符串值,无法继续向下遍历`); } pathSegments.push(nextNode.HOME); currentNode = nextNode; } } return pathSegments.join("/"); }
3. 测试验证
用示例输入验证函数效果:
console.log(buildRoute(r, "r.ACCOUNT.ADDRESSES.DETAIL")); // 输出:"start/account/addresses/:addressId" console.log(buildRoute(r, "r.INVENTORY.CATEGORIES")); // 输出:"start/warehouse/categories" console.log(buildRoute(r, "r.INVENTORY.CATEGORIES.CATEGORY.PRODUCTS.PRODUCT")); // 输出:"start/warehouse/categories/:categoryId/products/:productId"
内容的提问来源于stack exchange,提问作者crivella
相关产品推荐
相关产品推荐

