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

如何在PubSub模式中根据输入参数实现可变回调类型?

解决方案

首先我们需要建立事件名称与对应数据类型的映射关系,让TypeScript能根据订阅/发布的事件名自动推导参数类型,实现类型安全的PubSub。

步骤1:定义事件-数据类型映射

先明确每个事件名称对应的数据结构,用一个类型映射来统一管理:

// 事件名称与对应数据类型的映射,核心类型定义
type NameDataMap = {
  foo: { 
    a?: { foo: number },
    b?: { foo: boolean },
    c?: { foo: string }
  },
  bar: { 
    a: { foo: number } // bar事件仅传递a字段,且为必填
  },
  baz: { 
    b: { foo: boolean }, // baz事件传递b和c字段,均为必填
    c: { foo: string }
  }
}

// 从映射中自动推导事件名称类型,避免重复定义
type Names = keyof NameDataMap

// 针对每个事件的回调类型
type Callback<N extends Names> = (props: NameDataMap[N]) => any

步骤2:重构PubSub类

基于上面的类型映射,修改类的成员和方法,让它们能根据事件名自动匹配类型:

class PubSub {
  // 订阅者集合:每个事件对应其专属类型的回调数组
  subscribers: { [N in Names]: Callback<N>[] } = {} as any

  subscribe = <N extends Names>(name: N, callback: Callback<N>) => {
    // 确保订阅者数组存在
    if (!Array.isArray(this.subscribers[name])) {
      this.subscribers[name] = []
    }
    this.subscribers[name].push(callback)
  }

  publish = <N extends Names>(name: N, data: NameDataMap[N]) => {
    const subscribers = this.subscribers[name]
    subscribers?.forEach(subscriber => subscriber(data))
  }
}

步骤3:测试类型约束

现在使用PubSub时,TypeScript会自动根据事件名校验参数类型:

const ps = new PubSub()

// 订阅bar事件:回调仅能接收{ a: { foo: number } },访问其他字段会报错
ps.subscribe('bar', ({ a }) => console.log(a.foo))
// ❌ 错误示例:如果尝试访问b,TypeScript会提示“属性b不存在于类型{ a: { foo: number } }”
// ps.subscribe('bar', ({ b }) => console.log(b.foo))

// 订阅foo事件:回调能接收全部字段
ps.subscribe('foo', ({ a, b, c }) => {
  a?.foo && console.log(a.foo)
  b?.foo && console.log(b.foo)
  c?.foo && console.log(c.foo)
})

// 订阅baz事件:回调仅能接收{ b: { foo: boolean }, c: { foo: string } }
ps.subscribe('baz', ({ b, c }) => {
  console.log(b.foo, c.foo)
})

// 发布事件时,数据类型也会自动匹配
ps.publish('bar', { a: { foo: 0 } }) // 正确
// ❌ 错误示例:bar事件不能传递b字段
// ps.publish('bar', { b: { foo: true } })

关于额外需求的说明

通过定义NameDataMap这个核心类型映射,subscribe和publish方法可以共享同一套类型规则,不需要手动为每个方法重复编写类型判断。只要修改NameDataMap,所有相关方法的类型约束会自动同步,实现了“智能类型识别”的效果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 05:22:33