강의에 사용된 키노트 다운로드받기(PDF 포맷)
타입은 집합이다
타입스크립트의 '타입'은 사실 여러개의 값을 포함하는 '집합'입니다. 집합은 동일한 속성을 갖는 여러개의 요소들을 하나의 그룹으로 묶은 단위를 말합니다.따라서 다음 그림처럼 여러개의 숫자 값들을 묶어 놓은 집합을 타입스크립트에서는 number 타입이라고 부릅니다.

그렇다면 오직 하나의 값만 포함하는 타입인 Number Literal 타입은 어떤 집합 일까요? 예를 들어 20 이라는 Number Literal 타입이 존재한다면 이 타입은 다음 그림과 같이 딱 하나의 값만 포함하는 아주 작은 집합이라고 볼 수 있습니다.

그리고 이 20 이라는 타입에 속하는 요소인 숫자 20은 이 사실 집합 외에도 Number 타입이라는 거대한 집합에도 속하는 값입니다. 20도 결국 숫자이기 때문입니다. 그러므로 결국 모든 Number Literal 타입은 Number 타입이라는 거대한 집합에 포함되는 부분 집합으로 볼 수 있습니다.

사실 타입스크립트의 모든 타입들은 집합으로써 서로 포함하고 또 포함되는 이런 관계를 갖습니다. 그리고 이런 관계에서 Number 타입처럼 다른 타입을 포함하는 타입을 슈퍼 타입(부모 타입)이라고 부릅니다. 반대는 서브 타입(자식 타입)이라고 합니다.

이 관계를 계층처럼 표시하면 다음과 같은 그림이 됩니다.

그런데 위와 같은 그림을 우리는 이미 어디선가 한번 본 적 있습니다.
맞습니다 2섹션 초반에 살펴봤던 타입 계층도입니다.

결국 이 타입 계층도가 설명해주고 있는 것은 타입스크립트가 제공하는 여러가지 기본 타입들간의 집합으로써의 부모-자식 관계 였던 것 입니다. 여기까지 이해했다면 우리는 이제 다음으로 넘어가 이런 타입간의 관계를 어떻게 이용할 수 있는지 살펴봐야 합니다.
타입 호환성
이제 우리는 타입 호환성에 대해 이해할 수 있습니다.
타입 호환성이란 예를 들어 A와 B 두개의 타입이 존재할 때 A 타입의 값을 B 타입으로 취급해도 괜찮은지 판단하는 것을 의미합니다. 그래서 만약 A 타입의 값이 B 타입의 값으로 취급 되어도 괜찮다면 호환된다고 하고 안된다면 호환되지 않는다고 합니다.
예를 들어 다음 그림처럼 Number 타입과 Number Literal 타입이 있을 때 서브 타입인 Number Literal 타입의 값을 슈퍼 타입인 Number 타입의 값으로 취급하는 것은 가능합니다. 그러나 반대로는 불가능합니다.
그 이유는 Number 타입이 더 큰 타입이기 때문입니다.

이건 마치 정사각형과 직사각형의 관계와 비슷합니다. 정사각형을 직사각형으로 취급하는건 괜찮지만 반대로 직사각형을 정사각형으로 취급하는건 안되는 것 처럼 더 작은 타입의 값을 더 큰 타입의 값으로 취급하는 것은(ex : 정사각형은 직사각형이다) 상관없지만 반대(ex : 직사각형은 정사각형이다)로는 안되는 겁니다.

다음과 같은 코드는 문제가 되지 않습니다.

Number 타입의 변수 num1을 선언하고 값으로 10을 할당합니다. 그리고 10(Number Literal) 타입의 변수 num2를 선언하고 값으로 역시 10을 할당합니다.
이때 num1에 num2의 값을 저장하는건 가능합니다. 변수 num1의 타입이 더 큰 타입(Number 타입)이기 때문입니다.
그런데 다음과 같이 반대로는 안됩니다.

이번에는 num2에 num1의 값을 대입합니다. 이는 Number 타입의 값을 Number Literal 타입의 변수에 할당하는 것이고 더 나아가 Number 타입의 값을 Number Literal 타입의 값으로 취급 하겠다는 것 입니다. 이렇게 더 큰 타입의 값을 더 작은 타입의 값으로 취급하는 것은 안된다고 앞서 살펴보았습니다.
그런데 왜 안되는 걸까요? 집합으로 생각해보면 이해하기 쉽습니다.
변수 num1은 Number 타입이므로 10외에도 999나 -123123 같은 다양한 숫자 값을 담을 수 있습니다. 마치 직사각형에는 여러 종류의 사각형이 포함되는 것과 비슷합니다. 그러나 변수 num2는 Number Literal 타입이므로 10외의 다른 값은 절대 담을 수 없습니다.
그러므로 num2에 num1의 값을 저장하게 되면 문제가 발생할 가능성이 굉장히 큽니다. 그래서 이렇게는 불가능한 것 입니다.
따라서 타입스크립트에서는 이렇게 슈퍼타입의 값을 서브타입의 값으로 취급하는것을 허용하지 않습니다. 반대로는 허용합니다.

그리고 특별히 서브 타입의 값을 슈퍼 타입의 값으로 취급하는 것은 업 캐스팅 이라고 부르고 반대는 다운캐스팅이라고 부릅니다. 따라서 쉽게 정리하면 업캐스팅은 모든 상황에 가능하지만 다운 캐스팅은 대부분의 상황에 불가능하다고 할 수 있습니다.
