[TS] Union과 Intersection & Union vs Enum
Union
Union은or연산자라고 보면 된다.
- 원시 타입
function logPrimitiveType(value: string | number | boolean): void {
// string 이거나 number 이거나 boolean
console.log(value);
}
- 객체 타입
interface Person {
name: string;
age: number;
}
interface Developer {
name: string;
kindOf: string;
}
function logObjectType(value: Person | Developer): void {
// Person 이거나 Developer
console.log(value)
}
객체타입의 경우 프로퍼티를 사용하려 할 때 Person과 Developer의 공통 프로퍼티만 error없이 사용할 수 있고 공통되지않는 프로퍼티는 타입가드를 거쳐야만 error없이 사용할 수 있다.
타입가드란?: 특정 타입으로 타입의 범위를 좁혀나가는(필터링 하는) 과정
function logObjectType(value: Person | Developer): void {
// OK
console.log(value.name)
// Error
console.log(value.age)
console.log(value.kindOf)
}
이를 이해하며 or연산자는 이것도 되고 저것도 되는 것이기에 타입들 내부의 모든 프로퍼티를 사용할 수 있어야되지 않나? 싶었지만 함수 내부에서 사용될 값의 특징을 생각해보면 위와 같은 방식이 옳다는 것을 알 수 있다.
우리는 Person | Developer를 사용하기를 원한다.
그 말인 즉슨 값으로 Person이 들어올지 Developer가 들어올지 알 수 없다라는 것이다.

때문에 타입을 추론할 때 둘 중에 어느 것을 사용해도 상관없는 프로퍼티인 name은 타입가드없이 사용할 수 있고 age나 kindOf는 타입가드 과정을 거쳐야만 안전한 코드를 작성할 수 있으므로 위와 같이 동작한다.
Intersection
Intersection은and연산자라고 보면 된다.
- 원시 타입
function logPrimitiveType(value: string & number & boolean): void {
// value === never
console.log(value);
}
- 객체 타입
interface Person {
name: string;
age: number;
}
interface Developer {
name: string;
kindOf: string;
}
function logObjectType(value: Person & Developer): void {
// Person 이면서 Developer
console.log(value)
}
intersection의 경우는 실무에서 잘 쓰이지 않는다고 한다.
그 이유를 알아보자.
원시타입
우선 원시타입의 경우 하위타입과 intersection하지 않는 이상 never로 추론된다.
위의 예시로 보면 string이면서 number이면서 boolean이어야하는데 이는 사실상 불가능한 타입이기 때문이다.
만약 boolean과 null을 intersection하면 null로 판정된다.
때문에 원시타입에서는 사실상 intersection을 사용할 필요가 없다.
객체타입
객체 타입의 경우 역시 굳이 사용할 필요가 없다.
function logObjectType(value: Person & Developer): void {
// OK
console.log(value.name)
console.log(value.age)
console.log(value.kindOf)
}
위의 예시를 보면 Person이면서 Developer인 value를 받기 때문에 함수 몸체에서 내부 프로퍼티를 모두 사용할 수 있어 편해보이지만 intersection은 and연산자와 같다고 했다.
이게 무슨 뜻일까?
한마디로 Person과 Developer 둘 모두를 충족시키는 값이 전달되어야 한다는 것이다.

당연히 Person과 Developer모두를 충족하는 값이 전달될 것이기 때문에 함수 몸체에서 둘 모두의 프로퍼티를 사용해도 문제가 없던 것이다.
이게 과연 장점으로 작용할 수 있을까?
아마 호출 시점을 보면 얘기가 달라질 것이다.
logObjectType({ name: 'son', age: 27, kindOf: 'front' });
위의 호출문을 보면 Person이면서 Developer인 객체를 넣어주었다.
하나라도 만족하지 않는다면 타입에러가 난다.
그럼 생각해보자 { name: 'son', age: 27, kindOf: 'front' } 이 녀석은 무슨 타입일까?
그렇다, 사실 상 객체타입에서 intersection은 새로운 타입을 생성하는 것과 다른게 없다.
하지만 해당 타입을 명시하고 사용하는 것이 아니기 때문에 예측도가 떨어진다.
때문에 intersection을 쓸거면 차라리 새로운 타입을 확장하거나 생성해서 사용하는 것이 훨씬 안전하다.
Enum vs Union
이번에 union과 enum을 공부해보며 각각의 장단점을 비교해보고 무엇을 사용하는 것이 더 유리할지 고민해보았다.
Enum
장점
먼저 enum의 경우 내부 속성을 자동완성해주는 기능을 제공하기 때문에 속성 값을 몰라도 추상객체명만 알면 된다. 라는 장점이 있다.
하지만 union 역시 특정 타입이 아닌 값을 명시해주면 enum처럼 자동완성 기능을 사용할 수
있다.
단점
하지만 enum은 js 내부적으로 지원하지 않기 때문에 js로 컴파일하면 객체가 생성된다.
이는 곧 런타임에 영향을 미친다는 것인데 타입을 사용할 뿐인데 런타임에 영향을 미친다는 것이 아쉽다.
물론 const 키워드를 붙이면 컴파일을 하더라도 객체가 생성되지 않지만 이를 떠나서도 union과 대비되게 import구문이 필요하다는 점 역시 단점으로 작용한다.
Union
장점
- 타입가드만 잘해주면
type에 따른api를 구분하여 사용할 수 있다. import하지 않아도 타입 힌트를 제공한다.- 런타임에 영향을 주지 않는다.
결론
enum이 불편하거나 좋지 않은 자료형은 아니지만 union을 썼을 때의 장점이 좀 더 명확하기 때문에 여러 값을 가진 타입을 만들고 싶을 때 union을 더 선호하려 한다.
참고자료
Author And Source
이 문제에 관하여([TS] Union과 Intersection & Union vs Enum), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@sonwj0915/TS-Union과-Intersection-Union-vs-Enum저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)