TypeScript定义嵌套递归路由类型时VS Code报错如何解决?
问题原因
你遇到的类型报错根源出在RoutingVariants的索引签名定义上:
type RoutingVariants = { list: string, add: string, get: string, [key: string]: RoutingVariants | string, // 问题在这里 };
这个索引签名声明了所有字符串类型的key对应的值的类型是RoutingVariants | string联合类型,当你访问Routes.user.invoices的时候,TS无法确定这个值到底是字符串还是子路由对象,所以你继续访问.get属性的时候,TS会判定字符串类型上不存在get属性,因此抛出错误。
解决方案
推荐用类型推断+校验函数的写法,既能保留完整的自动补全能力,又能保证路由结构符合你的规则:
type GlobalRoutingT = 'user' | 'listing'; type RoutingVariants = { list: string; add: string; get: string; [key: string]: RoutingVariants | string; }; // 路由定义校验函数,既约束结构符合要求,又保留你写的路由对象的精确类型 function defineRoutes<T extends Record<GlobalRoutingT, RoutingVariants>>(routes: T) { return routes; } export const Routes = defineRoutes({ user: { list: '/user', add: '/user/add', get: '/user/:id', invoices: { list: '/user/invoices', add: '/user/invoices/add', get: '/user/invoices/:id', } }, listing: { list: '/listing', add: '/listing/add', get: '/listing/:id', }, });
修改后你再访问Routes.user.invoices.get就不会有报错,TS会自动识别invoices是子路由对象类型,自动补全也完全正常。如果你写错了顶层路由key,或者某个路由节点缺少list/add/get属性,TS也会及时给出错误提示。
如果不想改结构,也可以用类型断言临时绕过报错,不推荐长期使用:
<Route path={(Routes.user.invoices as RoutingVariants).get} exact > <GetInvoice /> </Route>
内容的提问来源于stack exchange,提问作者Alex Pokydko
相关产品推荐
相关产品推荐

