You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何构建TypeScript事件结构以支持事件专属中间件参数?

解决方案:类型安全的事件驱动中间件框架类型设计

核心思路

通过映射类型+泛型约束将事件类型与专属增强属性绑定,避免冗余的undefined属性,同时支持灵活扩展和非一一对应的事件-属性关系。

具体实现步骤

1. 定义通用中间件基础上下文

先抽离所有事件共享的增强项:

// 通用中间件增强属性:所有事件都会包含这些
type BaseMiddlewareContext = {
  next: () => Promise<void>;
  context: Record<string, unknown>;
};

// 示例事件载荷类型(根据实际业务定义)
type MsgEvent = {
  id: string;
  content: string;
};

type NotificationEvent = {
  title: string;
  level: 'info' | 'warn' | 'error';
};

2. 定义事件-专属属性映射

用映射类型明确每个事件类型对应的专属增强属性,支持一个事件绑定多个属性、多个事件共享同一属性:

// 事件类型与专属属性的映射表
type EventSpecificProps = {
  // message事件拥有message属性
  message: { message: MsgEvent };
  // alert事件同样拥有message属性(实现非一一对应)
  alert: { message: MsgEvent };
  // notification事件拥有notification属性
  notification: { notification: NotificationEvent };
  // system事件同时拥有message和notification属性
  system: { message: MsgEvent } & { notification: NotificationEvent };
};

// 生成指定事件的完整中间件参数类型
type MiddlewareArgs<T extends keyof EventSpecificProps> = BaseMiddlewareContext & EventSpecificProps[T];

3. 重构wrapMiddleware为泛型函数

让函数根据传入的事件类型自动推导对应的参数类型,解决类型不兼容问题:

function wrapMiddleware<T extends keyof EventSpecificProps>(
  eventType: T,
  middleware: (args: MiddlewareArgs<T>) => Promise<void>
) {
  // 这里实现你的中间件包装逻辑:
  // 1. 获取原始事件载荷
  // 2. 合并BaseMiddlewareContext和对应事件的专属属性
  // 3. 调用传入的middleware
  // 示例伪代码:
  const baseContext: BaseMiddlewareContext = {
    next: async () => {},
    context: {}
  };
  const specificProps = getEventSpecificProps(eventType); // 需自行实现该函数
  const args = { ...baseContext, ...specificProps } as MiddlewareArgs<T>;
  return middleware(args);
}

4. 类型守卫实现安全的属性访问

如果需要在通用中间件中判断事件类型并访问专属属性,可添加类型守卫:

// 判断是否为拥有message属性的事件
function hasMessageProp<T extends keyof EventSpecificProps>(
  args: MiddlewareArgs<T>
): args is MiddlewareArgs<'message' | 'alert' | 'system'> {
  return 'message' in args;
}

// 使用示例
wrapMiddleware('system', async (args) => {
  // 直接访问专属属性,类型完全安全
  console.log(args.notification.title);
  
  if (hasMessageProp(args)) {
    // 类型守卫后可安全访问message属性
    console.log(args.message.content);
  }
  
  await args.next();
});

方案优势

  • 无冗余属性:非对应事件不会出现message: undefined这类冗余定义
  • 类型安全:完全避免as类型断言,编辑器自动补全专属属性
  • 易扩展:新增事件/属性只需在EventSpecificProps中添加对应条目
  • 支持灵活映射:轻松实现一个属性对应多个事件、一个事件对应多个属性的场景

内容的提问来源于stack exchange,提问作者fil maj

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 05:35:13