I'm using next-connect with next.js & typescript, and I want to create a middleware that adds some fields to request object and infer the new request type. The code below:
// multipart middleware
export type NextApiRequestMultipart = NextApiRequest & {
files: Files;
fields: Fields;
};
export function multipart(
config?: Options
) {
return async (
req: NextApiRequest,
res: NextApiResponse,
next: NextHandler
) => {
const { files, fields } = await parseForm(req, config);
(req as NextApiRequestMultipart).files = files;
(req as NextApiRequestMultipart).fields = fields;
return next();
};
}
export router().post(
multipart({ multiples: false }),
async (req, res) => {
// I want to access properties without statically typing the request
const { files, fields } = req;
}
);
StackBlitz repo: see code
I managed to implement as sample solution. Here is the code demo: stakc-blitz modified
Sample description of the approach
I have not tested it but I wanted to show the approach.
We need a controller router builder to do that. And this controller builder will need to "stack" the types additions to the Request object of all middleware.
A sample
In order to extract the middleware type - I need to have it stated someware. That is why I introduced a decorated middleware.
Here is the abstraction over the Decorate middleware:
Now in the ControllerBuilder we can "extract the type" of each middleware and "stack" them by returning new instance with unin type: ReqeustType so far united with the addition the new middleware will add
Here is a sample middleware implementation of. We only need to state the additional properties of the request, which the builder will set. The process function has to return a Promise of those props, ensuring that all is set according to the middleware type contract.
And finally a sample usage:
The builder is not 100% complete, my intention was to show the approach. I would probably modify it so that a set of middlwares can be used.
Note that it behaves as Builder until handle is called. So it is immutable and can be chained and result reused
Something like this:
Link to the demo again: stakc-blitz modified