这里最简单的解决方案是创建builder函数,并创建类似于链表数据结构的东西。
考虑一下exmaple:
interface Route<Path extends string> {
path: Path;
prepare(params: PathArgs<Path>): void;
}
type PathParams<
Path extends string
> = Path extends `:${infer Param}/${infer Rest}`
? Param | PathParams<Rest>
: Path extends `:${infer Param}`
? Param
: Path extends `${infer _Prefix}:${infer Rest}`
? PathParams<`:${Rest}`>
: never;
type PathArgs<Path extends string> = { [K in PathParams<Path>]: string };
type ValidRoute = `/${string}/:${string}`
const route = <
Path extends string,
Routes extends Route<`${Path}${ValidRoute}`>[]
>(
path: Path,
prepare: (param: PathArgs<Path>) => void,
...routes: Routes
) => ({
path,
prepare,
routes
})
const routes = <
Str extends string,
Elem extends Route<Str>[]
>(...elems: [...Elem]) =>
elems
const result = [
route(`/dashboard/:siteId`, (arg) => { },
route(`/dashboard/:siteId/friend/:friendId`, (arg) => { }),
route(`/dashboard/:siteId/widgets/:widgetId`, (arg) => { },)
),
route(`/menu/:optioId`, (arg) => { },
route(`/menu/:optioId/select/:selectId`, (arg) => { })
)
]
Playground
啊
arg
论点推断正确。不需要创建复杂的递归数据结构。
试着把
/menu/:optioId/select/:selectId
进入
dashboard
名称空间:
const result = [
route(`/dashboard/:siteId`, (arg) => { },
route(`/dashboard/:siteId/friend/:friendId`, (arg) => { }),
route(`/dashboard/:siteId/widgets/:widgetId`, (arg) => { },),
route(`/menu/:optioId/select/:selectId`, (arg) => { }) // error
),
]
你会得到一个错误,因为
仪表板
命名空间要求字符串具有
仪表板
.