MST

星途 面试题库

面试题:TypeScript 中 Express 中间件类型扩展与复杂业务逻辑的融合

在一个企业级 Express 应用中,存在多层中间件嵌套,并且不同的业务逻辑分支需要不同的 `req` 类型扩展。例如,用户认证中间件需要添加 `user` 属性,支付相关中间件需要添加 `paymentInfo` 属性,且这些属性的类型可能相互依赖(如 `paymentInfo` 中的 `userId` 需与 `user` 中的 `id` 类型匹配)。请使用 TypeScript 设计一个完整的解决方案,涵盖类型定义、中间件实现以及如何在复杂业务逻辑中确保类型安全和一致性,详细描述设计架构和关键实现步骤,并给出核心代码示例。
28.5万 热度难度
前端开发TypeScript

知识考点

AI 面试

面试题答案

一键面试

1. 类型定义

首先,定义基础的 Request 扩展类型。假设 user 类型和 paymentInfo 类型如下:

// 定义用户类型
type User = {
  id: string;
  name: string;
  // 其他用户相关属性
};

// 定义支付信息类型,其中 userId 与 User 中的 id 匹配
type PaymentInfo = {
  userId: string;
  amount: number;
  // 其他支付相关属性
};

// 定义 Express 请求扩展类型
declare global {
  namespace Express {
    interface Request {
      user?: User;
      paymentInfo?: PaymentInfo;
    }
  }
}

2. 中间件实现

用户认证中间件

import express, { Request, Response, NextFunction } from 'express';

const userAuthMiddleware = (): ((req: Request, res: Response, next: NextFunction) => void) => {
  return (req, res, next) => {
    // 模拟用户认证逻辑,假设认证成功后获取到用户信息
    const user: User = { id: '123', name: 'John Doe' };
    req.user = user;
    next();
  };
};

支付相关中间件

const paymentMiddleware = (): ((req: Request, res: Response, next: NextFunction) => void) => {
  return (req, res, next) => {
    if (!req.user) {
      return res.status(401).send('User not authenticated');
    }
    // 模拟支付信息获取逻辑,确保 userId 与 user 中的 id 匹配
    const paymentInfo: PaymentInfo = { userId: req.user.id, amount: 100 };
    req.paymentInfo = paymentInfo;
    next();
  };
};

3. 应用中间件并确保类型安全和一致性

const app = express();

// 使用用户认证中间件
app.use(userAuthMiddleware());
// 使用支付相关中间件
app.use(paymentMiddleware());

// 处理业务逻辑的路由,确保类型安全
app.get('/payment', (req, res) => {
  if (!req.paymentInfo) {
    return res.status(500).send('Payment info not available');
  }
  res.send(`Payment amount: ${req.paymentInfo.amount}`);
});

const port = 3000;
app.listen(port, () => {
  console.log(`Server running on port ${port}`);
});

设计架构和关键实现步骤总结

  1. 类型定义:通过 declare global 扩展 Express.Request 接口,定义不同业务逻辑需要的属性类型,并确保属性类型之间的依赖关系。
  2. 中间件实现:每个中间件负责添加特定的 req 属性,并进行必要的逻辑处理,如用户认证中间件添加 user 属性,支付中间件确保 user 已认证并添加 paymentInfo 属性。
  3. 应用中间件:在 Express 应用中依次使用中间件,确保每个中间件按顺序执行,并在后续的路由处理中可以安全地使用扩展的 req 属性,从而确保整个业务逻辑中的类型安全和一致性。