본문 바로가기
공부

[TS] 이펙티브 타입스크립트 #26

by jaeeedev 2023. 4. 2.

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

문자열의 경우

type Language = "JavaScript" | "TypeScript" | "Python";
function setLanguage(language: Language) {
  /* ... */
}

setLanguage("JavaScript"); // OK

let language = "JavaScript";
setLanguage(language);
// Argument of type 'string' is not assignable to parameter of type 'Language'

language를 변수로 분리해서 함수의 인자로 사용하는 코드이다.
language는 string으로 추론되는데 setLanguage 함수는 Language 타입인 인수만 들어갈 수 있어서 타입 체크에 걸린다.

해결 방법

  • language의 타입을 명시적으로 제한하기
let language: Language = "JavaScript";
setLanguage(language);
  • language를 상수로 선언하기
const language = "JavaScript"; // "JavaScript"

튜플의 경우

function panTo(where: [number, number]) {
  /* ... */
}
const loc = [10, 20]; // number[]
panTo(loc); // Argument of type 'number[]' is not assignable to parameter of type '[number, number]'.

loc은 길이를 알 수 없는 숫자 배열로 인식하여 number[]로 추론된다. 때문에 길이가 정해진 튜플 타입에 부합하지 않는다.

해결 방법

  • 타입 선언 제공하기
const loc: [number, number] = [10, 20];
panTo(loc);
  • as const 사용하기
const loc = [10, 20] as const;
panTo(loc); // Argument of type 'readonly [10, 20]' is not assignable to parameter of type '[number, number]'.

// readonly 구문 추가

function panTo(where: readonly [number, number]) {
  /* ... */
}
const loc = [10, 20] as const;
panTo(loc); // OK

as const는 과하게 정확하고 panTo는 where가 불변이라고 보장하지 않는 상태라서 오류 발생 -> readonly 구문 추가

 

// 솔직히 여기는 이해가 잘 안간다..

콜백의 경우

function callWithRandomNumbers(fn: (n1: number, n2: number) => void) {
  fn(Math.random(), Math.random());
}

callWithRandomNumbers((a, b) => {
  a; // number
  b; // number
  console.log(a + b);
});

문맥을 읽어서 오류가 발생하지 않음

function callWithRandomNumbers(fn: (n1: number, n2: number) => void) {
  fn(Math.random(), Math.random());
}
const fn = (a, b) => {
  // Parameter 'a' implicitly has an 'any' type
  // Parameter 'b' implicitly has an 'any' type
  console.log(a + b);
};
callWithRandomNumbers(fn);

함수 fn을 분리함(문맥이 존재하지 않음) -> noImplicitAny 오류에 걸린다.

해결 방법

매개변수에 타입 구문 추가하기

const fn = (a: number, b: number) => {
  console.log(a + b);
};

callWithRandomNumbers(fn);

댓글