TypeScript의 교차 유형(Intersection Types)은 모든 원래 유형의 속성 및 메소드를 결합하여 복합 유형을 생성할 수 있게 해주는 기능입니다. 이는 클래스를 과도하게 상속하지 않고도 유연하고 확장 가능한 데이터 구조를 구축할 수 있는 강력한 도구입니다. 이 구조는 유형 간의 & 연산자를 사용하여 구현됩니다.
TypeScript는 초창기부터 "또는"을 표현하기 위해 합집합 유형(|)을 지원해왔지만, 서로 독립적인 여러 인터페이스 또는 유형의 속성을 가진 객체를 설명해야 하는 문제가 종종 발생합니다. 이럴 때 교차 유형(&)을 사용하게 됩니다 — 객체는 모든 인터페이스의 모든 속성에 만족해야 합니다.
주요 복잡성 중 하나는 교차된 유형에서 동일한 속성 이름이 충돌할 때와, 그들의 타입차이로 인하여 최종 결합된 타입의 정확성, 프라이빗 또는 보호된 필드를 가진 클래스를 결합할 때의 문제가 발생하는 것입니다. 또한 교차 유형을 합집합(Union types)과 혼동하여 컴파일 오류나 객체 작업 오류를 유발하는 경우가 많습니다.
교차 유형은 결합된 유형에서 모든 속성을 집계하며, 속성의 이름이 일치할 경우 두 유형 모두에 대한 준수가 요구됩니다. 이는 인터페이스와 type-별칭 모두에 사용됩니다.
interface A { foo: string; } interface B { bar: number; } type AB = A & B; const item: AB = { foo: "hello", bar: 123 }; // 올바름
만약 동일한 이름의 속성이 교차될 경우, 타입이 일치해야 하며, 그렇지 않으면 오류가 발생합니다:
interface X { val: string; } interface Y { val: number; } // type Z = X & Y; // 오류: val 불일치
주요 특징:
& 연산자는 두 유형의 모든 속성을 결합합니다 (인터페이스와 type-별칭).유형이 교차되는데 일부 속성이 호환되지 않는 유형을 가질 경우 어떻게 됩니까? (예: 하나는 string이고 다른 하나는 number)
컴파일 오류가 발생합니다. 속성이 동시에 string과 number일 수 없기 때문입니다.
프라이빗 또는 보호된 속성을 가진 클래스를 교차할 수 있습니까?
가능하지만, 동일한 이름을 가진 필드가 접근 유형이 다른 경우, 결과는 유효하지 않으며 TypeScript는 오류를 발생시킵니다.
교차 유형은 합집합 유형(|)과 어떻게 다릅니까?
교차 유형 (A & B)은 객체가 두 유형 모두를 동시에 요구하고, 합집합 (A | B)은 최소한 하나의 유형에 해당하기를 요구합니다. 예를 들어:
type U = A | B; // foo 또는 bar 또는 둘 다 가능 type I = A & B; // 필수적으로 두 속성 필요
개발자가 몇 가지 일치하지 않는 인터페이스를 교차하여 유형을 생성할 경우; 속성이 충돌하여 디버깅하기 어려운 타입 오류가 발생합니다.
장점: 여러 유형의 기능을 빠르게 결합할 수 있습니다.
단점: 코드가 컴파일되지 않거나 암묵적인 버그가 존재하고 디버깅이 어렵습니다.
기능을 독립적인 인터페이스로 나누고 교차 유형을 통해 이를 조심스럽게 결합하여 최종 콤포지트 객체를 형성합니다.
장점: 확장 가능성, 테스트 및 확장의 용이성, 엄격한 계약
단점: 인터페이스 설계 및 조정에 추가 작업이 필요합니다.