如何用TypeScript更优地映射枚举/接口数据对应关系?
优化设备与Symbol/Parameter的类型映射方案
需求是实现设备(如烟雾传感器、按钮等)与对应Symbol、Parameter的严格绑定,确保特定设备只能访问匹配的Symbol和Parameter。当前用联合接口的方式实现,希望找到更优方案。
原实现代码
export enum IName { SmokeSensor = 'SmokeSensor', GasSensor = 'GasSensor', MotionSensor = 'MotionSensor', WindowSensor = 'WindowSensor', Sensor = 'Sensor', PushButton = 'PushButton', Switch = 'Switch', Temperature = 'Temperature', } export enum ISymbol { SS = 'SS', SG = 'SG', SM = 'SM', SW = 'SW', SE = 'SE', PI = 'PI', SI = 'SI', TI = 'TI', } export enum IParameter { TTT = 'TTT', OOO = '000', OFF = 'OFF', OON = 'OON', POS = '0', NEG = '1', } interface IActivateSensors { name: Omit<IName, 'Switch' & 'Temperature'> symbol: Omit<ISymbol, 'SI' & 'TI'> parameter: Pick<IParameter, 'TTT' & '000'> } interface ISwitchSensor { name: IName.Switch symbol: ISymbol.SI parameter: Pick<IParameter, 'OFF' & 'OON'> } interface ITemperatureSensor { name: IName.Temperature symbol: Omit<ISymbol, 'SI' & 'TI'> parameter: Pick<IParameter, 'TTT' & '000'> } export type Sensors = IActivateSensors | ITemperatureSensor | ISwitchSensor
优化方案:基于映射表的自动类型推导
这种方案通过单一数据源定义设备与Symbol/Parameter的对应关系,后续维护只需修改映射表,类型自动生成,避免重复定义接口,同时保证类型严格性。
// 保留原枚举定义 export enum IName { SmokeSensor = 'SmokeSensor', GasSensor = 'GasSensor', MotionSensor = 'MotionSensor', WindowSensor = 'WindowSensor', Sensor = 'Sensor', PushButton = 'PushButton', Switch = 'Switch', Temperature = 'Temperature', } export enum ISymbol { SS = 'SS', SG = 'SG', SM = 'SM', SW = 'SW', SE = 'SE', PI = 'PI', SI = 'SI', TI = 'TI', } export enum IParameter { TTT = 'TTT', OOO = '000', OFF = 'OFF', OON = 'OON', POS = '0', NEG = '1', } // 核心:定义设备与对应Symbol、Parameter的映射表 const DeviceConfigMap = { [IName.SmokeSensor]: { symbols: [ISymbol.SS] as const, parameters: [IParameter.OOO, IParameter.TTT] as const }, [IName.GasSensor]: { symbols: [ISymbol.SG] as const, parameters: [IParameter.OOO, IParameter.TTT] as const }, [IName.MotionSensor]: { symbols: [ISymbol.SM] as const, parameters: [IParameter.OOO, IParameter.TTT] as const }, [IName.WindowSensor]: { symbols: [ISymbol.SW] as const, parameters: [IParameter.OOO, IParameter.TTT] as const }, [IName.Sensor]: { symbols: [ISymbol.SE] as const, parameters: [IParameter.OOO, IParameter.TTT] as const }, [IName.PushButton]: { symbols: [ISymbol.PI] as const, parameters: [IParameter.OOO, IParameter.TTT] as const }, [IName.Switch]: { symbols: [ISymbol.SI] as const, parameters: [IParameter.OFF, IParameter.OON] as const }, [IName.Temperature]: { symbols: [ISymbol.TI] as const, parameters: [IParameter.TTT, IParameter.OOO] as const } } as const; // 自动推导设备类型联合 export type Sensor = { [K in keyof typeof DeviceConfigMap]: { name: K; symbol: typeof DeviceConfigMap[K]['symbols'][number]; parameter: typeof DeviceConfigMap[K]['parameters'][number]; } }[keyof typeof DeviceConfigMap];
方案优势
- 单一数据源:所有设备的对应关系集中在
DeviceConfigMap,新增/修改设备只需调整这个对象,无需修改类型定义 - 严格类型约束:自动推导的
Sensor类型会确保每个设备只能使用匹配的Symbol和Parameter,不会出现类型不匹配的情况 - 扩展性强:新增设备时,只需在映射表中添加对应条目,类型会自动更新,无需手动新增接口
- 代码更简洁:避免了重复定义多个接口,减少冗余代码
内容的提问来源于stack exchange,提问作者user18209107
相关产品推荐
相关产品推荐

