Есть ли способ сделать перегрузку метода в TypeScript?

Есть ли способ перегрузить метод в 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):

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

Ответ 1

В соответствии со спецификацией 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);
    }
}

Ответ 2

Обновление для ясности. Перегрузка методов в 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 {
  //...
}

Ответ 3

Желаю. Я тоже хочу эту функцию, но TypeScript должен взаимодействовать с нетипизированным JavaScript, который не имеет перегруженных методов. т.е. если ваш перегруженный метод вызывается из JavaScript, он может быть отправлен только в одну реализацию метода.

Есть несколько соответствующих обсуждений по codeplex. например

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

Я все еще думаю, что TypeScript должен генерировать все if'ing и переключения, поэтому нам не нужно было это делать.

Ответ 4

Почему бы не использовать необязательный интерфейс, определяемый свойствами в качестве аргумента функции.

Для случая в этом вопросе использование встроенного интерфейса, определенного с некоторыми необязательными свойствами, может только сделать код как-то ниже:

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 есть еще много новых и удобных продуктов, которые недоступны на устаревшем языке программирования, где дополнительная поддержка свойств в анонимном интерфейсе - такой подход для удовлетворения удобной зоны от перегрузки устаревшей функции, Я думаю.

Ответ 5

class User{
   name : string;
   age : number;
   constructor(name:string,age:number){
    this.name = name;
    this.age = age;
    console.log("User " +this.name+ " Created")
}
getName(name:string = ""):string{
    if(name != ""){
        return name + " " +this.name;
    }else{
        return this.name;
    }
  }

}

Я думаю, что это должно работать

Ответ 6

Javascript не имеет никакой концепции перегрузки. Typescript не является С# или Java.

Но вы можете реализовать перегрузку в Typescript.

Прочитайте этот пост http://www.gyanparkash.in/function-overloading-in-typescript/