TypeScript如何使用运行时数据映射替代interface?
问题根源
编译错误的核心是类型匹配逻辑偏差:
- 你定义的
CommandDataMap是运行时对象,存储的是类的构造函数本身,所以CommandDataMap[Command.COMMAND_1]的类型是typeof Command1Data(构造函数类型),不是你处理函数需要的Command1Data(实例类型) - 定义
CommandMap时直接写CommandDataMap[Value]属于把值直接当类型用,编译器首先会提示你要加typeof获取对象的类型,但加完之后拿到的是构造函数类型,和处理函数需要的实例类型仍然不匹配,因此会继续报函数签名不兼容的错误。 - 你把
const改成interface能编译的原因是:interface内声明的字段类型直接是实例类型,刚好符合处理函数的参数要求,但interface会在编译后被擦除,运行时不存在这个映射对象,因此会触发运行错误。
解决方案
用TypeScript内置的InstanceType<T>工具类型,从构造函数类型里提取对应的实例类型即可,只需要修改CommandMap的定义,不需要额外维护两份映射:
type CommandMap = { [Value in Command]: ( data: InstanceType<typeof CommandDataMap[Value]>, ) => void; };
修改后运行时的CommandDataMap可以正常保留用于plainToClass做数据转换,类型也能完全匹配,不会再有编译错误。
额外提示
你给出的示例代码中onIncomingData函数里使用的data变量没有定义,实际使用时需要补充为入参。
内容的提问来源于stack exchange,提问作者James
相关产品推荐
相关产品推荐

