我正在使用next-connect next.js & typescript,我希望创建一个中间件,它添加一些字段来请求对象并推断新的请求类型。守则如下:
// 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回购:见代码
发布于 2022-09-21 15:41:37
我设法实现为示例解决方案。这里是代码演示: stakc-blitz改进
示例描述的方法
我还没有测试过它,但我想展示它的方法。
我们需要一个控制器路由器建设者来做到这一点。该控制器构建器将需要“堆栈”所有中间件的请求对象中添加的类型。
样本
class ControllerBuilder<RequestType> {
addMiddleWare(middleWare): ControllerBuilder<RequestType & middlewareTypeAdditions> {
// implementation
}
}为了提取中间件类型-我需要让它声明一些软件。这就是为什么我引入了一个装饰中间件。
下面是装饰中间件的抽象:
abstract class DecoratedMiddleware<MiddlewareReqTypeAdditions> {
///
}现在,在ControllerBuilder中,我们可以“提取”每个中间件的类型,并通过返回带有unin类型的新实例来“堆栈”它们:到目前为止,ReqeustType与新中间件将添加的内容结合在一起。
class ControllerBuilder<RequestType> {
addMiddleWare(middleWare: DecoratedMiddleware<MiddlewareReqTypeAdditions>): ControllerBuilder<RequestType & MiddlewareReqTypeAdditions> {
// implementation
return new ControllerBuilder<>
}
}下面是一个中间件实现示例。我们只需要声明请求的附加属性,构建器将设置这些属性。process函数必须返回这些道具的承诺,确保所有这些都是根据中间件类型契约设置的。
type AuthRequestAddtion = {
role: string;
id: number | string;
hotelId: number;
};
class AuthMiddleware extends DecoratedMiddleware<AuthRequestAddtion> {
protected process: MuddlewareFunc<AuthRequestAddtion> = (req, res) => {
return Promise.resolve({
id: 1,
role: 'GUEST',
hotelId: 3,
});
};
}最后是一个示例用法:
ControllerBuilder.get(router(), '/with-weather')
.addMiddleware(authMiddleware)
.addMiddleware(multipartMiddleware)
.addMiddleware(weatherMiddleware)
.handle(async (req, res) => {
//now we have types for all the middlewares
const hotelId = req.hotelId;
const files = req.files;
const temp = req.weather.temperature;
res.status(200).json({ hotelId, files, temp });
});建筑商不是100%完成,我的意图是展示的方法。我可能会修改它,以便可以使用一组中间件。
请注意,在调用句柄之前,它以Builder的形式运行。因此,它是不可变的,并且可以被链锁和结果重用。
就像这样:
const authUserWithWeather = ControllerBuilder.create()
.addMiddleware(authMiddleware)
.addMiddleware(weatherMiddleware);
authUserWithWeather.get("/").handle(() => {});
authUserWithWeather
.addMiddleware(multipartMiddleware)
.get("/something")
.handle(() => {})再次链接到演示:stakc-blitz改进
https://stackoverflow.com/questions/73729967
复制相似问题