[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.)