如何构建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
相关产品推荐
相关产品推荐

