当前位置: 首页 > 知识库问答 >
问题:

如何在打字稿中进行方法重载?

龙高歌
2023-03-14

我想实现这样的目标:

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语言中做方法重载?

共有3个答案

司徒光霁
2023-03-14

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

有一些关于代码库的相关讨论。例如

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

我仍然认为TypeScript应该生成所有的if'ing和switching,这样我们就不需要这样做了。

冯文彬
2023-03-14

为清晰起见进行更新。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 {
  //...
}
爱海
2023-03-14

根据规范,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);
    }
}
 类似资料:
  • 有一个在角度和打字稿中使用的setTimeout示例: 在编译时,我得到了以下信息: 错误TS2322:类型“Timeout”不能分配给类型“number”。 我如何在typescript中使用setTimeout?

  • 我有一个抽象类,它有一个抽象的泛型方法,看起来像这样 然后我有一个扩展这个抽象类的类。因为是抽象的,所以我必须在子类中实现它。 看起来像这样 返回 我得到以下错误虽然 类型'某物[]'不能分配给类型'T[]'。 我尝试了一些方法来解决这个错误,但是为了让Typescript满意,似乎还必须使子实现通用化。在我从至。 因此,我想知道如何使我的代码与TypeScript 2.4.1兼容?

  • 我继承了一个打字稿项目(有.ts),但我?似乎无法弄清楚如何在打字稿文件中创建一个全局变量并访问另一个。 我是打字稿的新手,所以请耐心等待。 我没有使用Angular-看到了这个链接打字稿-声明可选的全局变量 任何指针高度赞赏

  • 我试图在我的模型中添加一个静态方法,但是如果我这样做了,我得到了这个错误:< code >一个接口只能扩展一个类或另一个接口。 这是我的代码: 错误来自

  • 我有以下代码: 我遇到一个错误,指向.find并说: “字符串”类型的变量中不存在属性find。我知道错误在说什么,但是我如何将< code>$modal定义为一个我可以使用< code >的变量。查找于? 同样,现在我在typescript世界里,有没有更好的方法来定义modal,而不是在这里将它定义为var?

  • 我的代码: 错误消息来自TypeScript(3.0)编译器: TS2322:类型“string[]”不可分配给类型“[string, string, string, string, string, string, string]”。“string[]”类型中缺少属性“0”。 如果我将字符串[]更改为只读数组 TS2322:“ReadonlyArray”类型不能分配给类型“[string,stri