oak
oak copied to clipboard
How to pass dynamic router context type to methods function agruments
So in the example below I am making a new oak router, and then I am using the .get method with takes a path then ...middlwares. In the /:id line, there is a anonymous arrow function with the argument ctx. This ctx object has an infered type that is passed by the .get method, and it is dynamic based on the first path string arugment. So ctx in this case is excepting their to be a parameter object with the key id, which is awesome for type safetly and ide intelligence. The ctx argument also has inferred types that carry to the ctx.respone and ctx.request nested objects and this is great.
The issue is I like to split my routers in one file and my router handlers in a different file, like in the router.get('/', handler) line. The handler function has a ctx argument but now its type is any and looses the inferred router context type. Obviously I can still code but then you kinda loose the point of typescript here, and your fly somewhat blind.
I would normally just create a custom type and pass it to the handler function for the arguments, but Oaks router has a dyanmic type that is determined by the first path argument, so there is no one size fits all type of ctx.
Is there is a way to pass the inferred dynamic type over? I know the docs show the middleware being created right on the .get method like router.get('/:id', (ctx) => {}); but that just makes a lot of messy code. I perfer to seperate my router, middleware, and handlers.
const router = new oak.Router();
const handler = async (ctx) => {};
router.get('/', handler)
router.get('/:id', (ctx) => {});
Thank you! :D
I actually came up with a pretty good generic solution that allows for type compile time type checking.
type oakHandler<T extends string> = (
ctx: oak.RouterContext<T>
) => Promise<void> | void;
blogRouter.get("/", getBlogList).get("/:id", getBlogById);
const getBlogById: oakHandler<"/:id"> = async (ctx) => {};
This allows me to seperate by code base and I can just pass a path string to <T> on oak.RouterContext and it will preserve type safety and now my ctx on my handler is type aware and also ctx.params is object aware!