개발 기술/타입스크립트

타입스크립트 타입, union & intersection

by GicoMomg (Lux) 2021. 10. 19.

이번에는 타입스크립트의 union과 intersection타입에 대해 알아본다.



1. 유니온 타입(union type)

2) 유니온 타입이란?

(1) any타입의 경우

  • 우리가 함수의 파라미터 타입을 선언한다면 타입 체크가 가능하다.
  • 아래 예시는 string타입의 파라미터를 console에 출력하는 함수이다.
function logMessage(value:string) {
  console.log(value);
}
logMessage('adsda');

  • 이 함수에 올바른 타입의 파라미터를 넘기면 함수는 문제없이 작동된다.
logMessage('adsda');

  • 하지만, 만약 string 타입을 받는 파라미터에 number타입의 파라미터를 넘기면 에러가 발생한다.
logMessage(100);


그럼 파라미터가 여러 타입을 수용할 수 있도록 하면 안될까?
제일 간단한 방법으로는 파라미터의 타입을 any로 지정하는 것이다.

  • 파라미터의 타입을 any로 지정하면 어떤 타입이든 상관없이 파리미터를 받을 수 있다.
  • 하지만 타입이 any인 경우, 각 타입별 사용할 수 있는 함수를 추론해주지 않는다ㅜ
function logMessage(value:any) {
  console.log(value);
}

(2) 유니온 타입의 경우

그렇다면 string 혹은 number타입인 파리미터만 허용하고 각 타입별 유효한 함수도 알고 싶다면?
이런 경우에 바로 union type을 사용하는 것이다!

  • union typeA 혹은 B타입을 선언하는 방법이다. (A|B)
  • 이 타입을 사용하면 하나 이상의 타입을 선언할 수 있으며, 타입별 유효한 함수도 알 수 있다.
  • logMessage함수의 파라미터(value)는 string 혹은 number 타입이 가능하다.
function logMessage(value:string | number) { 
  console.log(value);
}

  • 유니온 타입이기 때문에 인자로 number 혹은 string을 넘길 수 있다.
logMessage('adsda');
logMessage(100);



2) 유니온타입의 특징

이러한 유니온 타입의 특징에는 무엇이 있을까? 한 번 알아보자!

(1) 여러 타입 선언 가능

  • 유니온 타입을 사용하게 되면 한가지 이상의 타입을 선언할 수 있다.
  • 아래 코드는 name 의 타입을 지정한 것으로, string 혹은 number, boolean이 가능한 변수가 된다.
const name: string | number | boolean;

(2) 타입 가드가 가능

  • 만약 유니온 타입의 파리미터가 string일 때만 쓸 수 있는 함수 혹은 number일 때만 쓸 수 있는 함수를 써야 한다면 어떻게 해야할까?
  • 이 경우에는 조건문을 사용해 타입별로 다른 처리를 해야 한다.
  • 이처럼 함수 내부에서 타입별 다른 처리를 하는 걸 타입가드라고 부른다.

실제로 타입가드를 쓰게 되면 어떻게 되는지 예시를 보자!

  • 만약 logMessage함수에서 파라미터의 타입에 따라 다른 처리를 한다고 가정하자.
  • 만약 인자의 타입이 number인 경우, number인 파라미터가 사용가능한 함수를 쓸 수 있다.
function logMessage(value:string | number) {
  if (typeof value === 'number') {
    value.toFixed();
  }
}


  • 혹은 인자의 타입이 string인 경우, string인 파라미터가 사용가능한 함수를 쓸 수 있게 된다.
function logMessage(value:string | number) {
  if (typeof value === 'string') {
    value.replace();
  }
}


(3) 인터페이스를 유니온으로 사용가능

  • 인터페이스를 사용해 각각 다른 속성을 가지는 커스텀 타입을 생성했다.
interface Teacher {
  name: string;
  subject: string;
}

interface Student {
  name: string;
  age: string;
}

  • 그리고 getPerson함수의 인자(person)는 Teacher, Student을 유니온 타입으로 가지도록 했다.
function getPerson(person: Teacher | Student) {
  ...
}

그렇다면 getPerson함수 내부에서 person이 접근할 수 있는 속성은 무엇일까?
name, subject, age 전부다일까? 답은 아니다.

  • 실제로는 공통 속성만 접근할 수 있다.
  • 그 이유는 유니온 타입은 AB 중 하나를 타입으로 가지는데, 만약 공통된 속성이 아닌 각각 존재하는 속성을 불러온다면 이건 타입적으로 불안정하기 때문이다.


아니 그러면 Teacher타입의 subject속성값은 접근하려면 어떻게 해야할까? 이 경우에는 in을 사용한다!

  • 만약 personage속성이 있다면(속성 in 파리미터) person.age를 쓸 수 있다.
function getPerson(person: Teacher | Student) {
  if ('age' in person) {
    console.log(person.age)
  }
}





2. 인터섹션 타입(intersection type)

1) 인터섹션 타입이란?

  • 인터섹션 타입은 여러 타입을 모두 만족하는 타입을 말한다.
  • 그렇다면 hellostring, number, boolean을 모두 가지는 타입으로 선언하면 어떻게 될까?
var hello: string & number & boolean;

  • 위와 같이 선언하면 hello변수의 타입은 never가 된다.
  • 그 이유는 string이면서 number이고 boolean인 타입은 없기 때문이다.


아니 그럼 여러 타입을 다 가지지도 못하는데 왜 이 타입을 사용하는 걸까?

  • 그 이유는 인터섹션 타입의 경우, 커스텀 타입을 사용할 때 유용하기 때문이다.
  • personTeacher, Student 타입을 모두 가지는 파라미터이다.
  • 이 경우, 유니온 타입과 달리 Teacher에만 존재하던 age 에 접근 가능한 장점이 있다.
function getPerson(person: Teacher & Student) {
  console.log(person.subject)  //Teacher타입에만 존재하는 속성
}





3. 유니온과 인터섹션의 차이

  • 유니온은 A, B 타입 중 A 혹은 B타입에 해당하는 속성만 인자로 넘겨주면 된다.
function getPerson1(person: Teacher | Student) {}
getPerson1({ name: 'gg', subject: 'math'});
getPerson1({ name: 'bb', age: 30});

  • 하지만 인터섹션의 경우, A, B 두 타입에 존재하는 모든 속성을 인자로 넘겨줘야한다.
function getPerson2(person: Teacher & Student) {}
getPerson2({ name: 'gg', subject: 'math'});  //error
getPerson2({ name: 'bb', age: 30}); //error
getPerson2({ name: 'bb', age: 30, subject: 'math'}); //success



참고자료
_아래 링크로 가면 더 자세히 알 수 있습니다 :) _

반응형

댓글