아이템 26. 타입 추론에 문맥이 어떻게 사용되는지 이해하기

아이템 26. 타입 추론에 문맥이 어떻게 사용되는지 이해하기

아이템 26. 타입 추론에 문맥이 어떻게 사용되는지 이해하기 #

이번 아이템에서 말하는 문맥이란, 상수를 그대로 사용하지 않고 변수(?), 별칭(?)과 같은 것(=문맥)을 의미한다.

문맥을 사용했을 때, 타입 추론이 다르다는 것을 이야기하는 내용이다.

아래 예시는, 문맥을 활용했을 때 타입추론이 어떻게 변하는지 보여주는 예시이다.

type Language = 'Javascript' | 'TypeScript' | 'Python'

function setLanguage(language: Language) { /* ... */ }

// 예시 1 : 상수 직접 사용
setLanguage('Javascript');

// 예시 2 : 문맥 활용
let language = 'Javascript';
setLanguage(language);
         // ~~~~~~~~ 'string' 형식의 인수는
         //          'Language' 형식의 매개변수에 할당될 수 없습니다.

위 예시는 왜 오류가 나는지는 알 것이다.



해결 방법 #

  1. (명시적) 타입 선언
  2. 상수 const
  3. 상수 단언 (as const)



해결 방법 : (명시적) 타입 선언 #

let language: Language = 'Javascript';  // 타입 : Language
setLanguage(language);



해결 방법 : 상수 const #

const language = 'Javascript';  // 타입 : 'Javascript'
setLanguage(language);



해결 방법 : 상수 단언 as const #

상수(const)의 경우에는 ‘튜플’, ‘객체’, ‘콜백(함수)’ 사용 시에는 문제가 해결되지 않는다.

/* 문제 예시 : 튜플 */
function panTo(where: [number, number]) { /* ... */ }

panTo([10, 20]);    // OK

const loc = [10, 20];   // 타입 : number[]
panTo(loc);
   // ~~~ 'number[]' 형식의 인수는
   //     '[number, number]' 형식의 매개변수에 할당될 수 없습니다.

위 예시에서 const loc = [10, 20]number[] 로 타입이 추론되어 오류가 발생한다.


/* 문제 예시 : 객체 */
type Language = 'Javascript' | 'TypeScript' | 'Python';
interface GovernedLanguage {
    language: Language;
    organization: string;
}

function complain(language: GovernedLanguage) { /* ... */ }

const ts = {
    language: 'TypeScript',     // 타입 : string
    organization: 'Mycrosoft',  // 타입 : string
};

complain(ts);
      // ~~ '{ language: string; organization: string; }' 형식의 인수는
      //    'GovernedLanguage' 형식의 매개변수에 할당될 수 없습니다.
      //    'language' 속성의 형식이 호환되지 않습니다.
      //    'string' 형식은 'Language' 형식에 할당될 수 없습니다.

위 예시에서 language: 'TypeScript'string 로 타입이 추론되어 오류가 발생한다.


이때는 아래 방법으로 해결 가능하다.

  1. 타입 선언
  2. 상수 단언 (as const, 상수 문맥)
    1. 다만, as const 의 경우 readonly 타입으로 적용되기 때문에 readonly 관련 오류가 또 발생할 수 있다.
/* 예시 : 타입 선언 */

const loc: [number, number] = [10, 20];
panTo(loc);
/* 예시 : 상수 단언 */

const loc = [10, 20] as const;
panTo(loc);
   // ~~~ 'readonly [10, 20]' 형식은 'readonly' 이며
   //     변경 가능한 형식 '[number, number]'에 할당할 수 없습니다.

즉, 함수의 타입 시그니처를 수정할 수 없다면 타입 선언을 하면 된다.



요약 & 정리 #

  • (문맥에서 타입 추론 오류 시) 타입 선언, const, as const 를 사용할 수 있다.
  • 변수를 뽑아서 사용할 때 오류가 발생한다면 타입 선언을 추가하자.
  • 변수가 정말로 상수(readonly)라면 상수 단언(as const)을 사용해야 한다.
    • 단, readonly 타입에 주의하자.