我有基类GenericSetting
,它是大约10种或更多类型的子类。
export class GenericSetting {
configuration: SettingArgs
constructor(args: SettingArgs) {
this.configuration = args
}
}
你可以看到它还接收了参数,这些参数是子类的子类,以解释子类所需的其他属性。
然后我创建了第100个设置,尽可能紧凑
FocusPos = new LensValuedSetting({ componentId:LensModule, key:"Focus-ActuatorPosition", displayName:"@{ActuatorPosition}", categories:["@{Lens}", "@{Focus}"], mode:EditMode.ReadOnly, stepSize:0, ctx:{ canId:7, dataType:"UInt16", bit:-1, startByte:2, rounding:1 }})
FocusAuxActive = new LensValuedSetting({ componentId:LensModule, key:"Focus-AuxInputDeviceActive", displayName:"@{AuxInputDeviceActive}", categories:["@{Lens}", "@{Focus}"], mode:EditMode.ReadOnly, stepSize:0, ctx:{ canId:36, dataType:"Byte", bit:1, startByte:6, rounding:1 }}, )
FocusAuxPos = new LensValuedSetting({ componentId:LensModule, key:"Focus-AuxInputDevicePosition", displayName:"@{AuxInputDevicePosition}", categories:["@{Lens}", "@{Focus}"], mode:EditMode.ReadOnly, stepSize:0, ctx:{ canId:36, dataType:"Int16", bit:-1, startByte:2, rounding:1 }}, )
问题在于,由于TypeScript只是推断传递的参数,args
参数在运行时实际上是object
类型,也绕过了所有这些子类设置参数的构造函数。
现在我想我会在基础构造函数中创建TypeScript中的类型保护类型,并Object.apply()
像这样:
export class GenericSetting {
configuration: SettingArgs
constructor(args: SettingArgs) {
const typedArgs = new <HOW DO I GET CTOR OF ARGS TYPE?>()
Object.assign(typedArgs, args)
this.configuration = typedArgs
}
}
显然我在运行时没有关于类型保护/推断类型的信息,所以有没有办法在一个地方做到这一点?我必须在每个子类中编写这个逻辑吗?
答案 0 :(得分:0)
在使用泛型的不同尝试之后(在更复杂的类层次结构中非常繁琐)我发现了一个有点可行的解决方案 - 即在...Args
类型上定义一个额外的属性:_cfgType:any
,我可以现在像这样传递到...Args
对象:
FocusPos = new LensValuedSetting({ _cfgType:LensValuedSettingArgs, componentId:LensModule, key:"Focus-ActuatorPosition", displayName:"@{ActuatorPosition}", categories:["@{Lens}", "@{Focus}"], mode:EditMode.ReadOnly, stepSize:0, ctx:{ canId:7, dataType:"UInt16", bit:-1, startByte:2, rounding:1 }})
我的GenericSettings基类构造函数现在看起来像这样,并将入站args
转换为正确的类型,应用相应子类的所有设置默认值:
export class GenericSetting extends ItemBase {
configuration:SettingArgs
constructor(args:SettingArgs) {
if (!isNullOrUndefined(args._cfgType)) {
const typedArgs = new args._cfgType()
Object.assign(typedArgs, args)
args = typedArgs
}
args['__type'] = args['__proto__'].constructor.name
super(args)
this.configuration = args
}
}
我不确定这是否是最优雅的方式,但至少对我的代码来说是最小的入侵。
答案 1 :(得分:0)
看起来你需要的是泛型。
export class GenericSetting<T extends Configuration> extends ItemBase {
configuration: T
constructor(configClass: new (args: SettingArgs): T, args: SettingArgs) {
const typedArgs = new configClass(args)
...
}
}
另一方面,在typedArgs
内构建GenericSetting
的需求是什么?施工过程似乎不依赖于GenericSetting
,因此通常更好地将施工过程保持在外面。
即
constructor(public configInstance: ...) { }