游戏引擎绑定中TypeScript消息与Body泛型类型关联优化需求
解决方案:让TypeScript自动推导消息对应的Body类型
核心问题在于当前的Message<TBody>是无差异的空类型,TypeScript无法通过不同的Message实例区分对应的Body类型。我们可以通过给Message类型添加唯一类型标记+建立消息-类型映射的方式,实现自动类型推导,无需编写冗长的重载或联合类型代码,同时满足message与body参数分离的要求。
步骤1:修改引擎侧的类型声明
首先调整Message类型和相关函数,让类型系统能关联消息标识与Body类型:
/** Engine external functions */ // 定义全局消息映射,绑定消息名称和对应的Body类型 export type MessageMap = { move: { x: number, y: number }, hit: { damage: number } }; // 给Message类型添加唯一类型标记(仅用于类型区分,无需实际实现) export type Message<T extends keyof MessageMap> = { readonly __type: T; }; // 调整Message函数,根据传入的消息名返回对应类型的Message declare function Message<T extends keyof MessageMap>(s: T): Message<T>; // 基于MessageMap优化sendMessage的类型推断 declare function sendMessage<T extends keyof MessageMap>( message: Message<T>, body: MessageMap[T] ): void;
步骤2:用户侧的消息定义与发送
现在用户创建消息时无需手动指定类型,TypeScript会自动推导:
/** User code */ // 自动推导类型,无需手动标注Message<XXX> const MessageMove = Message("move"); const MessageHit = Message("hit"); // sendMessage类型推断正常,错误参数会直接报错 sendMessage(MessageMove, { x: 10, y: 20 }); // 类型正确 sendMessage(MessageHit, { damage: 100 }); // 类型正确 sendMessage(MessageMove, { damage: 50 }); // 类型报错(符合预期)
步骤3:优化recieveMessage的自动推导
现在recieveMessage可以基于MessageMap自动匹配message对应的body类型:
class MyActor { recieveMessage<T extends keyof MessageMap>( message: Message<T>, body: MessageMap[T] ) { if (message === MessageMove) { // body自动推断为{ x: number, y: number } console.log(body.x, body.y); } else if (message === MessageHit) { // body自动推断为{ damage: number } console.log(body.damage); } } }
扩展:支持动态添加消息
如果需要让用户自定义新消息,可以通过模块扩展的方式扩展MessageMap:
// 用户自定义消息扩展 declare module "./your-engine-module" { interface MessageMap { jump: { height: number }; } } // 新增消息自动识别类型 const MessageJump = Message("jump"); sendMessage(MessageJump, { height: 5 }); // 类型正确
内容的提问来源于stack exchange,提问作者Onni
相关产品推荐
相关产品推荐

