[英]TypeScript - Pass Dynamic Property Name to Children
I'm working on a routing library with nested routing where I'm trying to define a child handler function which infers the parent paths.我正在开发一个带有嵌套路由的路由库,我正在尝试定义一个子处理程序 function 来推断父路径。 The reason being is I have another type which can infer dynamic path parameters from a string (eg,
users/:id
to { id: string }
);原因是我有另一种可以从字符串推断动态路径参数的类型(例如,
users/:id
到{ id: string }
); so, I want to be able to pass down the inferred path parameters from parent routes to any and all child routes in each child's route handler function.因此,我希望能够将推断的路径参数从父路由传递到每个子路由处理程序 function 中的任何和所有子路由。
Here's what I have so far:这是我到目前为止所拥有的:
type RawRouterDefn<Namespace extends string = ""> = {
[K: string]: Handler<Namespace, typeof K> | RawRouterDefn<`${Namespace}/${typeof K}`>;
};
type Handler<DataPath extends string, Path extends string> = ((args: { dataPath: DataPath, path: Path }) => unknown)
type Router<Routes extends RawRouterDefn, DataPath extends string = ""> = {
[K in keyof Routes & string]: Routes[K] extends CallableFunction
? Handler<DataPath, K>
: Router<Routes[K], `${DataPath}/${K}`>;
};
function createRouter<T extends RawRouterDefn>(rawDefn: T): Router<T, ""> {
// Implementation not important right now
return {} as unknown as Router<T, "">
}
const router = createRouter({
some: {
deeply: {
nested: {
/**
* Here, dataPath should be inferred as `some/deeply/nested`,
* path should be `route`
*/
route: ({ dataPath, path }) => {}
},
},
},
});
const route = router.some.deeply.nested.route;
// Correctly inferred **after** function applied, I need it within the router definition
type Params = Parameters<typeof route>[0]
(And the link to the playground) (以及游乐场的链接)
I'm almost there, except dataPath
should be inferred as /some/deeply/nested
and not /${string}/${string}/${string}
and path
should be inferred as /route
and not /${string}
.我快到了,除了
dataPath
应该被推断为/some/deeply/nested
而不是/${string}/${string}/${string}
并且path
应该被推断为/route
而不是/${string}
. This suggests to me there's something I'm missing in the RawRouterDefn
type.这表明我在
RawRouterDefn
类型中缺少一些东西。
So it seems that I can correctly narrow the shape of the string, but no further with my current approach.所以看起来我可以正确地缩小字符串的形状,但我目前的方法没有进一步。
Again, I need it to be inferred when used as function arguments, not after.同样,当用作 function arguments 时,我需要推断它,而不是之后。
Quite close, just needed to do a little magic with the generics:非常接近,只需要用 generics 做一点魔法:
function createRouter<T extends RawRouterDefn, R extends Router<T, "">>(rawDefn: R): R {
And now it works: https://tsplay.dev/NDRE1W现在它可以工作了: https://tsplay.dev/NDRE1W
You need another generic to tell TypeScript that what you get in the function is exactly what you return.您需要另一个泛型来告诉 TypeScript 您在 function 中得到的正是您返回的。 Removing
T extends RawRouterDefn
and using R extends Router<RawRouterDefn, "">
breaks the inference, so uh, don't do it.删除
T extends RawRouterDefn
并使用R extends Router<RawRouterDefn, "">
会破坏推理,所以,不要这样做。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.