【问题标题】:Invokable interfaces with overloads具有重载的可调用接口
【发布时间】:2015-04-10 11:52:16
【问题描述】:

我有多种类型要关联(外部)函数。我决定将它们放在幕后数组中,如下所示:

var labelGenerators : ILabelGenerator[] = []

ILabelGenerator 应该是类型可以具有的不同形状的通用接口,例如:

interface ILabelGenerator{
  (container : SomeContainerObject, delta: IDeltaValues): string;
  (container : SomeContainerObject, x: number, y: number): string;
  (container : SomeContainerObject, x: Date, y: number): string;
}

现在,我不知道如何将项目添加到 labelGenerators 数组,因为如果我执行以下操作:

labelGenerators[0] = (container:SomeContainerObject, x:number, y: number) => {
   return "label 0"; //the real code uses the parameters
}

我收到一个类型 (container:SomeContainerObject, x:number, y: number) => string is not assignable to type ILabelGenerator 错误。

如何解决这个问题? (我使用的是 TypeScript 1.3,但由于我有大约 10 种形状的调用,1.4 的联合类型将非常笨拙)

【问题讨论】:

  • 如何使用labelGenerators 数组做一些有用的事情?不可能检查函数以知道应该使用哪个签名来调用它们。
  • 这将在内部使用并有据可查(数组中的索引也来自枚举器)。所以labelGenerators[LabelType.TimeStamp]( 为我提供了所有重载,开发人员能够在特定场景中选择“正确”的重载。如果我错过了所有的实现,我也会得到一个编译错误,这很好。

标签: interface typescript overloading


【解决方案1】:

这应该可以避免编译器错误,因为你明确告诉 TS:

labelGenerators[0] = <ILabelGenerator>(
     (container: SomeContainerObject, x: number, y: number) => { 
         return "label 0"; //the real code uses the parameters 
     });

【讨论】:

    【解决方案2】:

    您的原始界面没有说“它可以是这些中的任何一个”,它说“它将与所有这些兼容” - 以满足您必须使用扩展类型或实现所有适当的重载。

    您想要的界面是“它将是其中的一个”。在这种情况下,您应该实际创建包含实际合约的接口。合同中唯一的实现承诺是第一个参数的类型为SomeContainerObject。就附加参数而言,所有的赌注都没有了。

    合约允许调用代码知道它可以依赖什么。因此,我会使用以下接口:

    interface ILabelGenerator{
      (container: SomeContainerObject, ...additional: any[]): string;
    }
    

    使用此接口的原因是,这就是您对实现ILabelGenerator 的全部承诺。

    例如,当您键入以下内容时...

    labelGenerators[0](
    

    你会得到真实的真实反映。

    您的原始界面过度承诺,​​因为它暗示“您可以调用您的首选签名”。这个版本说“我不知道你在第一次争论后应该提供什么”。即这是事实!

    【讨论】:

    • 是的,这是一个(类型安全的)过度承诺——这对于面向外部的代码来说是一个糟糕的设计(它在内部使用并记录在案)。但是,labelGenerators[0]( 为我提供了所有重载,开发人员能够在特定场景中选择“正确”的重载,这很有帮助。如果我错过了所有的实现,我也会得到一个编译错误,这很好。
    【解决方案3】:

    因为第二个参数需要与所有签名兼容。使用 x:any

    【讨论】:

    • 这正是我试图避免的,无论是在接口定义中,还是在函数声明中。但是,一旦我将元素调用,它们就可以正常工作。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-26
    • 2014-01-26
    • 2012-12-06
    • 2017-09-13
    相关资源
    最近更新 更多