Есть ли способ сделать перегрузку метода в 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);
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 {
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 {
//...
}
Хотелось бы. Я тоже хочу эту функцию, но 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 не таким удобным, как в тех языках, которые поддерживают реальную функцию перегрузки.
Тем не менее, все еще есть много новых и удобных материалов, предоставляемых в машинописном тексте, которые недоступны в устаревшем языке программирования, где поддержка необязательных свойств в анонимном интерфейсе является таким подходом для удовлетворения комфортной зоны из-за перегрузки устаревшей функции, я думаю.
Javascript не имеет никакой концепции перегрузки. Typescript не является C# или Java.
Но вы можете реализовать перегрузку в Typescript.
Прочтите этот пост http://www.gyanparkash.in/function-overloading-in-typescript/
Если существует много вариантов перегрузки методов, другой способ - просто создать класс со всеми вашими аргументами внутри. Таким образом, вы можете передать только нужный параметр в любом порядке.
class SomeMethodConfig {
stringParameter: string;
numberParameter: number;
/**
*
*/
constructor(stringParameter: string = '012', numberParameter?: number) { // different ways to make a param optional
this.numberParameter = 456; // you can put a default value here
this.stringParameter = stringParameter; // to pass a value throw the constructor if necessary
}
}
Также вы можете создать конструктор со значениями по умолчанию и / или передать некоторые обязательные аргументы. Тогда просто используйте вот так:
const config = new SomeMethodConfig('text');
config.numberParameter = 123; // initialize an optional parameter only if you want to do it
this.SomeMethod(config);
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;
}
}
}
Я думаю, что это должно работать