# 타입 추론(Type Inference)

타입 추론이란 타입스크립트가 코드를 해석해 나가는 동작을 의미합니다.

# 타입 추론의 기본

타입스크립트가 타입 추론을 해나가는 과정은 다음과 같습니다.

let x = 3;

위와 같이 x에 대한 타입을 따로 지정하지 않더라도 일단 xnumber로 간주됩니다. 이렇게 변수를 선언하거나 초기화 할 때 타입이 추론됩니다. 이외에도 변수, 속성, 인자의 기본 값, 함수의 반환 값 등을 설정할 때 타입 추론이 일어납니다.

# 가장 적절한 타입(Best Common Type)

타입은 보통 몇 개의 표현식(코드)을 바탕으로 타입을 추론합니다. 그리고 그 표현식을 이용하여 가장 근접한 타입을 추론하게 되는데 이 가장 근접한 타입을 Best Common Type이라고 합니다.

잠깐 예제를 보겠습니다.

let arr = [0, 1, null];

위 변수 arr의 타입을 추론하기 위해서는 배열의 각 아이템을 살펴봐야 합니다. 배열의 각 아이템의 타입은 크게 numbernull로 구분됩니다. 이 때 Best Common Type 알고리즘으로 다른 타입들과 가장 잘 호환되는 타입을 선정합니다.

# 문맥상의 타이핑(Contextual Typing)

타입스크립트에서 타입을 추론하는 또 하나의 방식은 바로 문맥상으로 타입을 결정하는 것입니다. 이 문맥상의 타이핑(타입 결정)은 코드의 위치(문맥)를 기준으로 일어납니다.

# 예시 코드 1

예시 코드를 보겠습니다.

window.onmousedown = function(mouseEvent) {
  console.log(mouseEvent.button);   //<- OK
  console.log(mouseEvent.kangaroo); //<- Error!
};

위 코드를 타입스크립트 검사기 관점에서 보면 window.onmousedown에 할당되는 함수의 타입을 추론하기 위해 window.onmousedown 타입을 검사합니다. 타입 검사가 끝나고 나면 함수의 타입이 마우스 이벤트와 연관이 있다고 추론하기 때문에 mouseEvent 인자에 button 속성은 있지만 kangaroo 속성은 없다고 결론을 내립니다.

# 예시 코드 2

다른 예제를 보겠습니다.

window.onscroll = function(uiEvent) {
  console.log(uiEvent.button); //<- Error!
}

앞의 예제와 마찬가지로 오른쪽의 함수는 window.onscroll에 할당되었기 때문에 함수의 인자 uiEventUIEvent으로 간주됩니다. 그래서 앞에서 봤던 MouseEvent와는 다르게 button 속성이 없다고 추론합니다. 그러므로 uiEvent.button에서 에러가 나죠.

여기서 만약 문맥상 타이핑을 좀 더 이해하고자 한다면 아래와 같이 코드를 바꿔볼 수도 있습니다.

const handler = function(uiEvent) {
  console.log(uiEvent.button); //<- OK
}

오른쪽 함수 표현식이 앞의 예제와 동일하지만 함수가 할당되는 변수만으로는 타입을 추정하기 어렵기 때문에 아무 에러가 나지 않습니다.

WARNING

위 코드에서 --noImplicitAny 옵션을 사용하면 에러납니다 😄

# 타입스크립트의 타입 체킹

타입 체킹에 있어서 타입스크립트의 지향점은 타입 체크는 값의 형태에 기반하여 이루어져야 한다는 점입니다. 이걸 Duck Typing 또는 Structural Subtyping 이라고 합니다.

TIP

Duck Typing : 객체의 변수 및 메서드의 집합이 객체의 타입을 결정하는 것을 의미. 동적 타이핑의 한 종류 Structural Subtyping : 객체의 실제 구조나 정의에 따라 타입을 결정하는 것을 의미