타입 추론 Type Inference

Gom·2021년 7월 17일
0

TypeScript

목록 보기
3/5

TypeScript는 기본적으로 변수 뒤에 콜론(:)과 타입 이름을 명시하는 타입 주석(type annotaion)을 함께 기재한다.

let n : number = 1; //type annotation
let m = 2; //type inference (변수 m의 타입은 number로 추론된다.)

타입추론(type inference)

😲❓ TypeScript라고해서 모든 변수에 일일이 타입을 지정해야 하는 것은 아니다. 타입 부분을 생략할 수 있다.

타입을 생략하면 벌어지는 일 = 타입 추론

변수의 타입 부분이 생략되면 대입 연산자의 오른쪽 값을 분석해 변수의 타입을 결정한다. 이를 타입 추론이라고 한다.

1. 타입 추론의 장점

  • 자바스크립트 소스코드와 호환성을 보장하는데 큰 역할을 한다. js 파일을 확장자만 ts로 바꾸면 타입스크립트 환경에서도 바로 동작한다.

  • 형식적인 코드 작성을 줄일 수 있다.

2. 타입 추론의 단점

  • 당연한 이야기지만 의도한 타입이 할당하는 값만으로 드러나지 않는 경우에는 여전히 타입 표기가 필요하다.
const oneOrThree: 1 | 3 = 3;

// const oneOrThree = 3;
// 3을 할당하는 것만으로는 1 | 3을 추론할 수 없다.

3. 타입 추론 방식

대부분의 경우 타입 추론은 직관적이지만 개발자가 의도치 않은 방향으로의 추론을 방지하기 위해 타입 추론 방식을 알아보자.

let x = 3; // number 타입으로 추론
const y = 3; // 3 타입으로 추론

3-1. 최적 공통 타입 (Best Common Type)

  • 의미 : 여러 표현식에서 타입 추론이 발생할 때의 접근법
  • 원리 : 모든 가능한 타입의 유니언 타입을 사용한다.
let x = [0, 1, null] // x의 타입 number | null
  • 특징 :
    단, 후보 타입들로부터 최적 공통 타입을 선택하지 때문에 모든 후보 타입을 포함하는 상위 타입이 존재해도 후보 타입 중 상위 타입이 존재하지 않으면 선택할 수 없다. 상위 타입으로 추론되길 원하는 경우 직접 상위 타입을 표기해야 한다. 그렇게 동작하지 않는 이유는 아래 예시를 통해 이해할 수 있다.
interface Animal {
  legs: number;
}

interface Dog extends Animal {
  bark(): void;
}

interface Cat extends Animal {
  meow(): void;
}

let dog: Dog;
let cat: Cat;
const dogAndCat = [dog, cat]; 
// dogAndCat의 타입은 Animal[]이 아닌 Array<Dog | Cat>으로 추론된다.

상위 타입으로 자동 추론되지 않는 이유

상위 타입인 Animal[]로 자동 추론하는 경우 아래 상황에서 오류가 발생한다.

interface Animal {
  legs: number;
}

interface Dog extends Animal {
  bark(): void;
}

interface Cat extends Animal {
  meow(): void;
}

interface Camel extends Animal {
  humps: number;
}

let dog: Dog;
let cat: Cat;
const dogAndCat = [dog, cat]; 

function getSoundFunction(dogOrCat: Animal[]) {
  if ('meow' in dogOrCat) {
    return dogOrCat.meow;
  } else {
    return dogOrCat.bark;
  }
}

dogAndCat.map(dogOrCat => getSoundFunction(dogOrCat));

dogAndCat 배열에는 Camel 타입의 변수가 존재하지 않음에도 위의 코드에서는 타입 에러가 발생한다. 이런 불편함을 막고자 최적 공통 타입에서의 타입 추론은 사용된 값들의 타입만을 재료로 사용한다.

3-2. 문맥상의 타입 (Contextual Type)

타입 추론은 할당 받는 값(왼쪽 항)의 타입 뿐 아니라
할당"하는" 값인 오른쪽 항에 대해서도 타입을 추론한다. 이렇게 추론된 타입을 contextual type이라 부른다. 문맥상 위치에 의해 타입이 암시될 때 발생한다.

window.onmousedown = function(mouseEvent) {
  console.log(mouseEvent.button); // 성공 (button 프로퍼티 존재)
  console.log(mouseEvent.a); // 오류 (a 프로퍼티는 없음을 추론 가능)
};
  • window.onmousedown(event: MouseEvent) => void라 추론한다.
  • 함수 내부에서 mouseEvent.buttonmouseEvent.a에 대한 타입 추론도 이루어진다.

만약 타입 표기가 주어진다면 문맥상 타입은 무시된다.

window.onmousedown = function(mouseEvent: any) {
  console.log(mouseEvent.a); // 오류 발생하지 않음.
};

참고자료
https://ahnheejong.gitbook.io/ts-for-jsdev/06-type-system-deepdive/type-assertion
https://typescript-kr.github.io/pages/type-inference.html

profile
안 되는 이유보다 가능한 방법을 찾을래요

0개의 댓글