TypeScript不支持直接的运算符重载(operator overloading)——只能通过函数/类在一定程度上模拟这种行为,因为JavaScript(以及TypeScript转译为JS)不允许改变标准运算符(+、*、-等)对用户定义类型的行为。
问题历史:在像C++或C#这样的语言中,可以为对象定义运算符的自定义行为。而在TypeScript(和JavaScript)中没有这样的功能,因为最终生成的代码是常规的JS代码,运算符与内部类型之间的关系是固定的。
问题所在:在开发包含抽象实体(例如,向量、矩阵、金额等)的类时,有时需要通过运算符方便地进行操作。TypeScript中没有原生实现这一点的语法。
解决方案:为了模拟运算符重载,可以创建具有直观名称的方法(add、mul、sub),有时使用静态方法或工具函数。此外,可以通过valueOf方法实现显式类型转换,但这不足以完全重载所有运算符,并且这个解决方案仅对某些原始值的运算符有效。
代码示例:
class Vector2D { constructor(public x: number, public y: number) {} add(v: Vector2D): Vector2D { return new Vector2D(this.x + v.x, this.y + v.y); } } const v1 = new Vector2D(1, 2); const v2 = new Vector2D(3, 4); const result = v1.add(v2); // Vector2D { x: 4, y: 6 }
关键特点:
add、sub)valueOf方法仅对某些运算符有效,受限如果定义了valueOf/toString,运算符+的重载对于类会有效吗?
不。valueOf仅影响转换为原始值时的行为。对于运算符+(例如字符串连接或数字相加),这可能会产生意外结果,其它运算符则无法配置。
class Currency { constructor(private amount: number) {} valueOf() { return this.amount; } } const c1 = new Currency(10); const c2 = new Currency(5); console.log(c1 + c2); // 15,但这不是Currency对象!
可以使用Proxy来重载TypeScript中的运算符吗?
不可以。Proxy允许拦截对属性和方法的访问,但不能处理运算符(+、*等),它们只能与内置类型一起工作。
通过接口或类型声明"重载"运算符可以吗?
不可以。在接口中只能描述方法和函数签名,无法像C#那样描述运算符重载(operator+)
开发者在Currency类中添加了valueOf,以便直接获取数字表示并执行数学运算(currency1 + currency2)。结果失去了语义;相加的结果是一个简单的数字,而不是货币对象,无法跟踪返回值的类型。
优点:
缺点:
在Vector类中实现了一个返回新Vector的add方法。类型明确,不存在模糊性。
优点:
缺点: