TypeScript如何根据同记录的event类型匹配data类型并定义数组类型
解决方案
你可以通过「映射类型+索引访问」的组合,先构造出当前泛型T下所有合法消息项的联合类型,直接赋值给dataStream$作为类型定义即可。
步骤1:构造通用工具类型
// 入参是MessageType的命名空间key,输出该命名空间下所有合法的消息项联合类型 type MessageStreamItem<Namespace extends keyof MessageType> = { [EventName in keyof MessageType[Namespace]]: { event: EventName; data: MessageType[Namespace][EventName]; } }[keyof MessageType[Namespace]];
步骤2:替换dataStream$的类型定义
class Subscriber<T extends keyof MessageType> { // 替换原有的any数组类型 private dataStream$: Array<MessageStreamItem<T>> = new Array(); nextItem<K extends keyof MessageType[T]>(): { event: K; data: MessageType[T][K]} { // 这里的类型断言是合理的:TS无法自动推导pop返回的联合类型和泛型K的对应关系,业务逻辑可以保证类型匹配 return this.dataStream$.pop() as { event: K; data: MessageType[T][K]}; } }
类型效果验证
- 当你实例化
const sseSub = new Subscriber<'sse'>()时,往dataStream$中插入数据时会自动校验event和data的匹配关系:插入{event: "task.completed", data: {completedAt: new Date()}}合法,插入{event: "task.completed", data: {startedAt: new Date()}}会直接报类型错误。 - 原有的
nextItem方法的类型约束完全保留,调用方法时的自动推导逻辑不受影响。
内容的提问来源于stack exchange,提问作者Tim Stephens
相关产品推荐
相关产品推荐

