Historia del problema
Muchos lenguajes estrictamente tipados (C++, C#, Python) permiten una descripción explícita de las sobrecargas para operadores (por ejemplo, +, -, *, ==) a nivel de clase. En TypeScript, al igual que en JavaScript, la sobrecarga de operadores no está presente a nivel del lenguaje por razones históricas y de arquitectura.
Problema
Cuando se necesita agregar soporte para operaciones aritméticas u otras operaciones para tipos complejos (por ejemplo, números complejos o vectores), no se puede modificar los operadores estándar. Esto limita la expresividad y requiere inventar patrones de contorno.
Solución
En TypeScript, se simula la sobrecarga de operadores a través de métodos nombrados de manera especial (por ejemplo, add, equals, multiply). Al equipar la clase con estos métodos, implementamos un comportamiento seguro para los tipos, aunque la sintaxis no es tan concisa como en C++.
Ejemplo de código:
class Vector { constructor(public x: number, public y: number) {} add(other: Vector): Vector { return new Vector(this.x + other.x, this.y + other.y); } equals(other: Vector): boolean { return this.x === other.x && this.y === other.y; } } const a = new Vector(1, 2); const b = new Vector(3, 4); const c = a.add(b); // Vector { x: 4, y: 6 } const eq = a.equals(b); // false
Características clave:
¿Es posible redefinir el comportamiento del operador "==" o "+" para la clase personalizada en TypeScript?
No, JavaScript (y TypeScript) no permite sobrecargar directamente los operadores estándar para objetos personalizados. Los operadores se aplican estrictamente de acuerdo con el estándar para Object, Number y otros primitivos. Cualquier intento de tal "redesplazamiento" resultará en un comportamiento incorrecto o inesperado o simplemente no funcionará.
¿Se puede usar valueOf o toString para influir indirectamente en los operadores?
En algunos casos, se puede usar valueOf (por ejemplo, para una conversión breve a número), pero solo para operadores que acceden al valor primitivo del objeto.
class Box { constructor(private v: number) {} valueOf() { return this.v; } } const a = new Box(10); console.log(a + 5); // 15 — funciona, pero para objetos complejos no es intuitivo
Pero para estructuras complejas y operadores lógicos, tiene sentido utilizar métodos explícitos.
¿Hay planes para agregar sobrecarga de operadores en TypeScript o ECMAScript?
En este momento, no hay planes aprobados: la sobrecarga de operadores, en principio, contradice el diseño de JS, ya que puede alterar significativamente el comportamiento de los objetos estándar y conducir a la inestabilidad del código.
Un desarrollador crea una clase Matrix, donde implementa valueOf/toString para su uso en expresiones matemáticas. Al sumar con números o cadenas, se obtienen resultados impredecibles, lo que hace imposible la tipificación estricta.
Pros:
Contras:
La clase Vector implementa métodos add, multiply, equals con una tipificación clara de los parámetros de entrada y salida. Los clientes de la clase utilizan explícitamente los métodos correspondientes, la semántica no se pierde y se asegura una tipificación estricta.
Pros:
Contras: