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

