Issue
I'm trying to get this router
function to infer the route params from a path provided, and to check that a plugin
has the correct function shape.
Here's what I have so far:
interface RouteConfig<Path extends string = string> {
hash?: string;
name: string;
path: Path;
plugins?: Array<RouterPlugin<Path>>;
search?: string;
}
type Route<Path extends string> = RouteConfig<Path> & {
plugins: Array<RouterPlugin<Path>>;
};
interface RouteContext<Params = { [key: string]: string | undefined }, Query = Record<string, string>> {
name: string;
params: Params;
query: Query;
url: URL;
}
type RouterPlugin<Path extends string> = (context: RouteContext<PathParams<Path>>) => void | Promise<void>;
type PathParams<Path extends string> = string extends Path
? Record<string, string | undefined>
: // eslint-disable-next-line @typescript-eslint/no-unused-vars
Path extends `${infer _Start}:${infer Param}/${infer Rest}`
? { [K in Param | keyof PathParams<Rest>]: string }
: // eslint-disable-next-line @typescript-eslint/no-unused-vars
Path extends `${infer _Start}:${infer Param}`
? { [K in Param]: string }
: Record<string, unknown>;
function createRouter<T extends RouteConfig>(config: T[]) {
//
}
const router = createRouter([
{
name: 'task',
path: '/tasks/:id',
plugins: [(ctx: { params: { id: string }}) => {}], // ERROR HERE
},
]);
And this is the error:
Property 'id' is missing in type 'Record<string, string | undefined>' but required in type '{ id: string; }'
Solution
Instead of trying to have the generic parameter be a RouteConfig, you should make it the array (tuple) of paths. Then you can map over that tuple and easily define each element of that tuple with Route<...>
:
function createRouter<Paths extends string[]>(config: [...{
[K in keyof Paths]: Route<Paths[K]>;
}]) {
//
}
And this works nicely:
// inferred as createRouter<["/tasks/:id", "/user/:name"]>
const router = createRouter([
{
name: "task",
path: "/tasks/:id",
plugins: [(ctx) => { ctx.params.id }], // okay
},
{
name: "by user",
path: "/user/:name",
plugins: [(ctx) => { ctx.params.name }], // okay
},
]);
Answered By - merryweather
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.