如何为服务端与客户端跨端调用事件定义对应的TypeScript类型
实现方案
1. 统一事件类型定义
首先放弃拆分枚举和函数类型命名空间的方案,直接定义全局共享的事件映射接口,一处定义两端复用:
// global/server-event.ts 服务端和客户端都可以导入这个文件的类型 export interface ServerEventMap { // 键是事件名称,值是该事件对应的自定义参数函数类型(不需要包含clientId参数) MyEvent1: (myArg1: string) => void MyEvent2: (myArg1: number, myArg2?: boolean) => number MyEvent3: () => Promise<string> // 后续新增事件仅需要在此处追加条目即可 }
2. 理解泛型工具逻辑
你找到的示例代码是最基础的函数类型透传泛型,核心作用是:
- 接收任意函数类型
U作为泛型参数 - 返回的新函数和原函数参数、返回值类型完全一致
我们基于这个逻辑扩展,就能实现框架方法的类型封装。
3. 封装框架方法获得类型提示
3.1 服务端addEvent封装
import type { ServerEventMap } from './global/server-event' // 封装原生framework.addEvent方法 export function useAddServerEvent<T extends keyof ServerEventMap>( eventName: T, // 回调第一个参数固定为clientId,后续参数匹配事件定义的参数列表 handler: (clientId: string, ...args: Parameters<ServerEventMap[T]>) => ReturnType<ServerEventMap[T]> ) { framework.addEvent(eventName, handler) }
3.2 客户端callRemote封装
import type { ServerEventMap } from './global/server-event' // 封装原生framework.callRemote方法 export async function useCallRemote<T extends keyof ServerEventMap>( eventName: T, // 入参自动匹配对应事件的参数列表 ...args: Parameters<ServerEventMap[T]> // 返回值自动包装为Promise,匹配事件定义的返回类型 ): Promise<Awaited<ReturnType<ServerEventMap[T]>>> { return framework.callRemote(eventName, ...args) }
4. 使用示例
服务端注册事件
输入事件名称时会自动补全所有已定义的事件,回调参数自动获得类型提示:
useAddServerEvent('MyEvent2', (clientId, myArg1, myArg2) => { // 自动推导:clientId为string类型,myArg1为number类型,myArg2为可选boolean类型 console.log(clientId, myArg1, myArg2) return myArg1 + 1 })
客户端调用事件
传参错误、事件名拼写错误都会触发TS语法报错,返回值类型自动推导:
// 自动校验参数:必须第一个参数传number,第二个可选传boolean const result = await useCallRemote('MyEvent2', 100, true) // 自动推导result为number类型
内容的提问来源于stack exchange,提问作者Alexandr Kat
相关产品推荐
相关产品推荐

