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