typescript - 获取编译时类型

时间:2018-01-06 19:02:19

标签: javascript typescript es6-class

我有基类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
  }
}

显然我在运行时没有关于类型保护/推断类型的信息,所以有没有办法在一个地方做到这一点?我必须在每个子类中编写这个逻辑吗?

2 个答案:

答案 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: ...) { }