有没有办法在类型签名语言中进行过载的方法?

我想实现这样的东西:

class TestClass {
    someMethod(stringParameter: string): void {
        alert("Variant #1: stringParameter = " + stringParameter);
    }

    someMethod(numberParameter: number, stringParameter: string): void {
        alert("Variant #2: numberParameter = " + numberParameter + ", stringParameter = " + stringParameter);
    }
}

var testClass = new TestClass();
testClass.someMethod("string for v#1");
testClass.someMethod(12345, "string for v#2");
.

这里是我不想做的一个例子(我真的讨厌在js中重载黑客的那部分):

class TestClass {
    private someMethod_Overload_string(stringParameter: string): void {
        // A lot of code could be here... I don't want to mix it with switch or if statement in general function
        alert("Variant #1: stringParameter = " + stringParameter);
    }

    private someMethod_Overload_number_string(numberParameter: number, stringParameter: string): void {
        alert("Variant #2: numberParameter = " + numberParameter + ", stringParameter = " + stringParameter);
    }

    private someMethod_Overload_string_number(stringParameter: string, numberParameter: number): void {
        alert("Variant #3: stringParameter = " + stringParameter + ", numberParameter = " + numberParameter);
    }

    public someMethod(stringParameter: string): void;
    public someMethod(numberParameter: number, stringParameter: string): void;
    public someMethod(stringParameter: string, numberParameter: number): void;

    public someMethod(): void {
        switch (arguments.length) {
        case 1:
            if(typeof arguments[0] == "string") {
                this.someMethod_Overload_string(arguments[0]);
                return;
            }
            return; // Unreachable area for this case, unnecessary return statement
        case 2:
            if ((typeof arguments[0] == "number") &&
                (typeof arguments[1] == "string")) {
                this.someMethod_Overload_number_string(arguments[0], arguments[1]);
            }
            else if ((typeof arguments[0] == "string") &&
                     (typeof arguments[1] == "number")) {
                this.someMethod_Overload_string_number(arguments[0], arguments[1]);
            }
            return; // Unreachable area for this case, unnecessary return statement
        }
    }
}


var testClass = new TestClass();
testClass.someMethod("string for v#1");
testClass.someMethod(12345, "string for v#2");
testClass.someMethod("string for v#3", 54321);
.

有帮助吗?

解决方案

根据规范,TypeScript确实支持方法重载,但它非常尴尬,包括大量手动工作检查参数类型。我认为这主要是因为最接近的方法可以在普通的javascript中重载,包括该检查,并且打字标注尝试不修改实际方法主体以避免任何不必要的运行时性能成本。

如果我理解正确,你必须先为每个过载写一个方法声明,然后是一个方法实现,该方法检查它的参数以决定调用哪个过载。实现的签名必须与所有过载都兼容。

class TestClass {
    someMethod(stringParameter: string): void;
    someMethod(numberParameter: number, stringParameter: string): void;

    someMethod(stringOrNumberParameter: any, stringParameter?: string): void {
        if (stringOrNumberParameter && typeof stringOrNumberParameter == "number")
            alert("Variant #2: numberParameter = " + stringOrNumberParameter + ", stringParameter = " + stringParameter);
        else
            alert("Variant #1: stringParameter = " + stringOrNumberParameter);
    }
}
.

其他提示

清晰度更新。方法中的方法重载是一个有用的功能,只要它允许您为需要表示的API创建现有库的类型定义。

在编写自己的代码时,您可能会避免使用可选或默认参数避免过载的认知开销。这是方法过载的更可读替代品,也可以保持您的API诚实,因为您将避免使用无线排序创建过载。

类型键标过载的一般定律是:

如果可以删除过载签名和所有测试通过,您不需要打字签名重载

您通常可以使用可选或默认参数或与Union类型的相同的事物,或者使用一点对象方向。

实际问题

实际问题要求过载:

someMethod(stringParameter: string): void {

someMethod(numberParameter: number, stringParameter: string): void {
.

现在甚至在支持具有单独实现的语言中的语言(注意:打字签名重载共享单个实现) - 程序员是在订购中提供一致性的建议。这将使签名:

someMethod(stringParameter: string): void {

someMethod(stringParameter: string, numberParameter: number): void {
.

始终需要stringParameter,因此它首先是。您可以将其写为工作类型ripper过载:

someMethod(stringParameter: string): void;
someMethod(stringParameter: string, numberParameter: number): void;
someMethod(stringParameter: string, numberParameter?: number): void {
    if (numberParameter != null) {
        // The number parameter is present...
    }
}
.

但遵循类型标准重载的定律,我们可以删除过载签名,所有测试仍将通过。

someMethod(stringParameter: string, numberParameter?: number): void {
    if (numberParameter != null) {
        // The number parameter is present...
    }
}
.

实际问题,在实际顺序

如果确定要持续到原始顺序,则重载将是:

someMethod(stringParameter: string): void;
someMethod(numberParameter: number, stringParameter: string): void;
someMethod(a: string | number, b?: string | number): void {
  let stringParameter: string;
  let numberParameter: number;

  if (typeof a === 'string') {
    stringParameter = a;
  } else {
    numberParameter = a;

    if (typeof b === 'string') {
      stringParameter = b;
    }
  }
}
. 现在是要解决参数的地方的很多分支,但如果你正在阅读这一点,你真的想保存这个命令......但是等待,如果我们应用Ringscript过载的法律,会发生什么?< / p>
someMethod(a: string | number, b?: string | number): void {
  let stringParameter: string;
  let numberParameter: number;

  if (typeof a === 'string') {
    stringParameter = a;
  } else {
    numberParameter = a;

    if (typeof b === 'string') {
      stringParameter = b;
    }
  }
}
.

已经足够的分支已经 当然,鉴于我们需要做的类型检查量......也许最好的答案只是有两个方法:
someMethod(stringParameter: string): void {
  this.someOtherMethod(0, stringParameter);
}

someOtherMethod(numberParameter: number, stringParameter: string): void {
  //...
}
.

我希望。我想要这个功能,但是需要使用没有重载的方法的UTTYPLED JavaScript互操作。即,如果从javascript调用过载的方法,那么它只能派出到一个方法实现。

有一些关于Codeplex的相关讨论。例如

https://typescript.codeplex.com/workitem/617

我仍然认为打字标语应该生成所有if'ing和切换,所以我们不需要做到这一点。

为什么不使用可选属性定义的接口函数参数..

对于此问题中的情况,使用具有某些可选属性定义的内联接口,只能直接制作类似于以下内容的代码:

class TestClass {

    someMethod(arg: { stringParameter: string, numberParameter?: number }): void {
        let numberParameterMsg = "Variant #1:";
        if (arg.numberParameter) {
            numberParameterMsg = `Variant #2: numberParameter = ${arg.numberParameter},`;
        }
        alert(`${numberParameterMsg} stringParameter = ${arg.stringParameter}`);
    }
}

var testClass = new TestClass();
testClass.someMethod({ stringParameter: "string for v#1" });
testClass.someMethod({ numberParameter: 12345, stringParameter: "string for v#2" });
.

因为在其他人的评论中提供的重载是如此,只是函数的不同签名列表,而无需支持与其他静态语言的相应的实现代码。因此,实施仍然必须在一个函数体中完成,这使得在类型中的功能过载的使用不像支持真正的重载功能的这些语言一样舒适。 然而,仍然存在许多新的和方便的类型,其中包含传统编程语言中的可用性,其中匿名接口中的可选属性支持是一种与遗留功能超载遇到舒适区域的方法,我认为。

javascript没有任何重载的概念。打字签名不是C#或Java。

但您可以在类型签字中实施重载。

阅读这篇文章 http://www.gyanparkash.in/function-ovingling-in-typescript/

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top