有没有办法在TypeScript中进行方法重载?

javascript typescript operator-overloading

49535 观看

5回复

有没有办法在TypeScript语言中进行方法重载?

我希望实现这样的目标:

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中重载hack的那部分):

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);
作者: Void-995 的来源 发布者: 2019 年 5 月 29 日

回应 (5)


120

决定

根据规范,TypeScript确实支持方法重载,但它非常笨拙并且包括许多手动工作检查参数类型。我认为这主要是因为在纯JavaScript中最接近方法重载的方法包括检查,TypeScript尝试不修改实际的方法体以避免任何不必要的运行时性能成本。

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

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);
    }
}
作者: svick 发布者: 02.10.2012 11:00

22

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

但是,在编写自己的代码时,您可能能够使用可选参数或默认参数来避免重载的认知开销。这是方法重载的更可读的替代方法,并且还可以保持您的API诚实,因为您将避免使用不直观的排序创建重载。

TypeScript重载的一般规律是:

如果您可以删除过载签名并且所有测试都通过,则不需要TypeScript重载

您通常可以使用可选或默认参数 - 或使用联合类型或使用一些面向对象来实现相同的功能。

实际问题

实际问题要求超载:

someMethod(stringParameter: string): void {

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

现在,即使在支持具有单独实现的重载的语言中(注意:TypeScript重载共享单个实现) - 程序员建议在排序中提供一致性。这将使签名:

someMethod(stringParameter: string): void {

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

stringParameter始终是必需的,所以先行。您可以将其写为有效的TypeScript重载:

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

但遵循TypeScript重载法则,我们可以删除重载签名,所有测试仍然会通过。

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;
    }
  }
}

现在有很多分支可以找出放置参数的位置,但如果你正在阅读这篇文章,你真的想保留这个顺序......但是等等,如果我们应用TypeScript重载法则会发生什么?

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 {
  //...
}
作者: Fenton 发布者: 02.10.2012 10:16

8

我希望。我也想要这个功能,但是TypeScript需要与没有重载方法的无类型JavaScript互操作。即如果从JavaScript调用重载方法,那么它只能被分派到一个方法实现。

关于codeplex的一些相关讨论。例如

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

我仍然认为TypeScript应该生成所有if'ing和切换,所以我们不需要这样做。

作者: nicopolyptic 发布者: 20.07.2013 02:11

1

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

对于这个问题的情况,使用一些可选属性定义的内联接口只能直接生成如下代码:

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" });

因为TypeScript中提供的重载是其他人的注释中提到的,只是函数的不同签名列表,而不支持其他静态语言的相应实现代码。因此,实现仍然只需要在一个函数体中完成,这使得在Typescript中使用函数重载不如支持真正重载特性的语言那么舒服。

然而,仍然有许多新的和方便的东西在typescript中提供,这在遗留编程语言中是不可用的,其中匿名界面中的可选属性支持是这样一种方法来满足传统函数重载的舒适区域,我认为。

作者: 千木郷 发布者: 10.12.2017 03:12

0

Javascript没有任何重载的概念。Typescript不是c#或Java。

但是你可以在Typescript中实现重载。

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

作者: Gyan 发布者: 08.12.2018 06:15
32x32