문제의 역사
많은 엄격한 타입의 언어들(C++, C#, Python)은 클래스 수준에서 연산자(예: +, -, *, ==)의 오버로딩을 명시적으로 정의하는 것을 허용합니다. 타입스크립트는 자바스크립트와 마찬가지로 역사적 및 아키텍처적 이유로 언어 수준에서 연산자 오버로딩을 지원하지 않습니다.
문제
복소수나 벡터와 같은 복합 타입에 대한 산술 연산 지원을 추가해야 할 때, 표준 연산자를 변경할 수 없습니다. 이는 표현력을 제한하고 우회 패턴을 발명해야 하도록 만듭니다.
해결책
타입스크립트에서는 특별히 이름이 지정된 메소드(예: 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
주요 특징들:
타입스크립트에서 자신의 클래스에 대해 '==' 또는 '+' 연산자의 동작을 재정의할 수 있나요?
아니요, 자바스크립트(및 타입스크립트)는 사용자 정의 객체에 대해 표준 연산자를 직접적으로 오버로딩하는 것을 허용하지 않습니다. 연산자는 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 — 작동하지만 복잡한 객체에 대해 직관적이지 않음
하지만 복잡한 구조와 논리 연산자에 대해서는 명시적인 메소드를 사용하는 것이 의미가 있습니다.
타입스크립트나 ECMAScript에 operator overloading을 추가할 계획이 있나요?
현재로서는 승인된 계획이 없습니다: 원칙적으로 연산자 오버로딩은 JS 디자인에 반하며, 이는 표준 객체의 동작을 크게 변경하고 코드의 불안정성을 초래할 수 있습니다.
개발자가 수학적 표현에 배치하기 위해 valueOf/toString을 구현하는 Matrix 클래스를 생성합니다. 숫자나 문자열과 더할 때 예측할 수 없는 결과가 나타나며, 엄격한 타입 지정이 불가능합니다.
장점:
단점:
Vector 클래스는 입력 및 출력 매개변수의 명확한 타입을 가진 add, multiply, equals 메소드를 구현합니다. 클래스의 클라이언트는 해당 메소드를 명시적으로 사용하며, 의미가 손실되지 않고 엄격한 타입 지정이 보장됩니다.
장점:
단점: