История вопроса
Многие строго типизированные языки (C++, C#, Python) позволяют явное описание перегрузок для операторов (например, +, -, *, ==) на уровне класса. В TypeScript, как и в JavaScript, операторная перегрузка отсутствует на уровне языка по историческим и архитектурным причинам.
Проблема
Когда нужно добавить поддержку арифметики или других операций для сложных типов (например, комплексных чисел или векторов), невозможно изменить стандартные операторы. Это ограничивает выразительность и требует изобретать обходные паттерны.
Решение
В TypeScript имитируют перегрузку операторов через специально названные методы (например, add, equals, multiply). Оснащая класс такими методами, мы реализуем типобезопасное поведение, хотя синтаксис выглядит не так лаконично, как в C++.
Пример кода:
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
Ключевые особенности:
Можно ли переопределить поведение оператора "==" или "+" для собственного класса в TypeScript?
Нет, JavaScript (и TypeScript) не позволяет напрямую разгрузить стандартные операторы для пользовательских объектов. Операторы применяются строго по стандарту для Object, Number и других примитивов. Любая попытка такого "переопределения" приведёт к неправильному или неожиданному поведению или просто не будет работать.
Можно ли использовать valueOf или toString для опосредованного влияния на операторы?
В некоторых случаях можно использовать valueOf (например, для краткого преобразования к числу), но только для операторов, которые обращаются к примитивному значению объекта.
class Box { constructor(private v: number) {} valueOf() { return this.v; } } const a = new Box(10); console.log(a + 5); // 15 — работает, но для сложных объектов неинтуитивно
Но для сложных структур и логических операторов имеет смысл использовать явные методы.
Есть ли планы по добавлению operator overloading в TypeScript или ECMAScript?
На данный момент нет утверждённых планов: принципиально перегрузка операторов противоречит дизайну JS, так как может существенно изменить поведение стандартных объектов и привести к нестабильности кода.
Разработчик создаёт класс Matrix, где реализует valueOf/toString для подстановки в математических выражениях. При сложении с числами или строками получаются непредсказуемые результаты, невозможна строгая типизация.
Плюсы:
Минусы:
Класс Vector реализует методы add, multiply, equals с чёткой типизацией входных и выходных параметров. Клиенты класса явно используют соответствующие методы, семантика не теряется, обеспечена строгая типизация.
Плюсы:
Минусы: