style link attribute javascript typescript

javascript - link - Método de sobrecarga?



title html (5)

¿Hay alguna forma de sobrecargar el método en lenguaje TypeScript?

Quiero lograr algo como esto:

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

Aquí hay un ejemplo de lo que no quiero hacer (realmente odio esa parte de sobrecargar el hack en 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);


¿Por qué no utilizar la interfaz definida como propiedad opcional como argumento de la función?

Para el caso en esta pregunta, el uso de una interfaz en línea definida con algunas propiedades opcionales solo podría hacer código directamente como algo a continuación:

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

Debido a que la sobrecarga proporcionada en TypeScript es, como se menciona en los comentarios de los demás, solo una lista de las firmas diferentes de la función sin dar soporte a los códigos de implementación correspondientes, como otros lenguajes estáticos. Por lo tanto, la implementación aún debe hacerse en un solo cuerpo de función, lo que hace que el uso de la sobrecarga de funciones en Typescript no sea tan cómodo como los lenguajes que soportan la función de sobrecarga real.

Sin embargo, todavía hay muchas cosas nuevas y convenientes en mecanografiado que no está disponible en el lenguaje de programación heredado, donde el soporte de propiedad opcional en una interfaz anónima es un enfoque para satisfacer la zona cómoda de la sobrecarga de funciones heredadas, creo.


Actualización para mayor claridad. La sobrecarga de métodos en TypeScript es una característica útil en la medida en que le permite crear definiciones de tipos para bibliotecas existentes con una API que necesita ser representada.

Sin embargo, al escribir su propio código, es posible que pueda evitar la sobrecarga cognitiva de las sobrecargas utilizando parámetros opcionales o predeterminados. Esta es la alternativa más legible a las sobrecargas de métodos y también mantiene su API honesta, ya que evitará crear sobrecargas con un orden poco intuitivo.

La ley general de las sobrecargas de TypeScript es:

Si puede eliminar las firmas de sobrecarga y pasar todas sus pruebas, no necesita sobrecargas de TypeScript

Por lo general, puede lograr lo mismo con parámetros opcionales o predeterminados, o con tipos de unión, o con un poco de orientación a objetos.

La pregunta real

La pregunta real pide una sobrecarga de:

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

Ahora, incluso en lenguajes que admiten sobrecargas con implementaciones separadas (nota: las sobrecargas de TypeScript comparten una sola implementación) - los programadores son consejos para proporcionar consistencia en los pedidos. Esto haría las firmas:

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

El stringParameter siempre es obligatorio, por lo que va primero. Puede escribir esto como una sobrecarga de TypeScript activa:

someMethod(stringParameter: string): void; someMethod(stringParameter: string, numberParameter: number): void; someMethod(stringParameter: string, numberParameter?: number): void { if (numberParameter != null) { // The number parameter is present... } }

Pero siguiendo la ley de las sobrecargas de TypeScript, podemos eliminar las firmas de sobrecarga y todas nuestras pruebas seguirán pasando.

someMethod(stringParameter: string, numberParameter?: number): void { if (numberParameter != null) { // The number parameter is present... } }

La pregunta real, en el orden real

Si estaba decidido a persistir con el pedido original, las sobrecargas serían:

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

Ahora que es una gran cantidad de ramificaciones para averiguar dónde poner los parámetros, pero realmente quería conservar este orden si está leyendo hasta aquí ... pero espera, ¿qué pasa si aplicamos la ley de sobrecargas de 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; } } }

Ya basta con ramificar

Por supuesto, dada la cantidad de verificación de tipos que tenemos que hacer ... tal vez la mejor respuesta es simplemente tener dos métodos:

someMethod(stringParameter: string): void { this.someOtherMethod(0, stringParameter); } someOtherMethod(numberParameter: number, stringParameter: string): void { //... }


Deseo. También quiero esta característica, pero TypeScript necesita ser interoperable con JavaScript sin tipo que no tiene métodos sobrecargados. es decir, si su método sobrecargado se llama desde JavaScript, solo se puede enviar a una implementación de método.

Hay algunas discusiones relevantes sobre codeplex. p.ej

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

Sigo pensando que TypeScript debería generar todos los if''ing y switching para que no tengamos que hacerlo.


Según la especificación, TypeScript admite la sobrecarga de métodos, pero es bastante incómoda e incluye una gran cantidad de trabajos manuales que comprueban los tipos de parámetros. Creo que es principalmente porque lo más cercano que se puede llegar a sobrecargar el método en JavaScript simple incluye esa comprobación también y TypeScript intenta no modificar los cuerpos de método reales para evitar cualquier costo de rendimiento en el tiempo de ejecución innecesario.

Si lo entiendo correctamente, primero debe escribir una declaración de método para cada una de las sobrecargas y luego una implementación de método que verifique sus argumentos para decidir a qué sobrecarga se llamó. La firma de la implementación debe ser compatible con todas las sobrecargas.

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


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

Creo que esto debería funcionar