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


вот пример того, что я не хочу делать (я действительно ненавижу эту часть перегрузки hack в 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);
724   4  

4 ответов:

согласно спецификации, 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);
    }
}

обновление для ясности. Перегрузка метода в TypeScript является полезной функцией, поскольку она позволяет создавать определения типов для существующих библиотек с API, который должен быть представлен.

при написании собственного кода, однако, вы вполне можете быть в состоянии избежать когнитивных накладных расходов перегрузок с помощью дополнительных или параметров по умолчанию. Это более читаемая альтернатива перегрузкам метода, а также сохраняет ваш API честным, поскольку вы избегаете создания перегрузок с неинтуитивными заказ.

общий закон перегрузки машинописного текста:

если вы можете удалить подписи перегрузки и все ваши тесты проходят, вам не нужны перегрузки TypeScript

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

Вопрос

фактический вопрос требует перегрузки оф:

someMethod(stringParameter: string): void {

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

теперь даже в языках, которые поддерживают перегрузки с отдельными реализациями (Примечание: перегрузки TypeScript разделяют одну реализацию) - программисты советуют обеспечить согласованность в заказе. Это сделало бы подписи:

someMethod(stringParameter: string): void {

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

The stringParameter всегда требуется, поэтому он идет первым. Вы можете написать это как рабочую перегрузку машинописного текста:

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

теперь это много ветвления, чтобы решить, где поместить параметры, но вы действительно хотели сохранить этот порядок, если Вы читаете это далеко... но подождите, что произойдет, если мы применим закон перегрузки машинописного текста?

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 {
  //...
}

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

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

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

Я все еще думаю, что TypeScript должен генерировать все 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" });

поскольку перегрузка, предоставляемая в TypeScript, является, как упоминалось в комментариях других, просто списком различных сигнатур функции без поддержки соответствующих кодов реализации, таких как другие статические языки. Таким образом, реализация все еще должна быть выполнена только в одном теле функции, что делает использование перегрузки функций в Typescript не столь удобным, как такие языки, поддерживающие реальную функцию перегрузки.

тем не менее, в typescript все еще есть много новых и удобных материалов, которые недоступны в устаревшем языке программирования, где поддержка дополнительных свойств в анонимном интерфейсе-это такой подход для удовлетворения комфортной зоны из наследия перегрузка функций, я думаю.

Comments

    Ничего не найдено.