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

如何在TypeScript中定义具备类型化数据结构的事件并实现严格校验

实现严格绑定关系的异构事件数组类型

核心采用**可辨识联合(判别联合)**设计思路,把事件标题e和关联数据d做强一一映射,从类型层面彻底杜绝事件与数据不匹配的非法写入,实现流程如下:

第一步:定义事件名与数据的映射关系

独立梳理所有事件的名称字面量,以及每个事件对应的数据结构,形成统一映射表,避免散写在各个对象里造成关联丢失:

type EventPayloadMap = {
  ROLE_CREATED: { roleId: number }
  ROLE_DELETED: { roleId: number }
  USER_CREATED: { userId: number }
}

第二步:生成绑定e、d关联的事件联合类型

基于映射表遍历生成所有合法的事件对象类型,形成完整的判别联合,让每一种事件的e取值和d的结构严格绑定:

type AppEvent = {
  [EventName in keyof EventPayloadMap]: {
    e: EventName
    d: EventPayloadMap[EventName]
  }
}[keyof EventPayloadMap]

第三步:定义受约束的事件数组类型

直接将数组类型指定为上述生成的事件联合类型,TypeScript会自动对数组内的每一项做精确校验:

type EventArray = AppEvent[]

实际校验效果

  • 符合映射规则的事件可正常通过类型检查:
const validEventList: EventArray = [
  {e: "ROLE_CREATED", d: { roleId: 2 }}, 
  {e: "ROLE_DELETED", d: { roleId: 3 }},
  {e: "USER_CREATED", d: { userId: 1 }}, 
]
  • 尝试给USER_CREATED事件搭配roleId结构的数据时,TypeScript会直接抛出编译错误,从语法层面拦截非法写入,这类代码完全无法通过类型校验:
// 代码无法通过TS类型检查
const invalidEventList: EventArray = [
  // 类型报错:e为"USER_CREATED"时,d必须匹配{ userId: number }结构,当前传入的d类型不匹配
  {e: "USER_CREATED", d: { roleId: 1 }}
]

常见避坑点

  • 不要使用宽泛的松散类型定义数组,比如直接写Array<{e: string, d: Record<string, number>}>,这类定义会完全丢失e和d的绑定关联,所有事件名都可以搭配任意数字属性对象,彻底失去严格约束能力。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.22 11:36:00