공부
[TS] 이펙티브 타입스크립트 #26
jaeeedev
2023. 4. 2. 21:49
타입 추론에 문맥이 어떻게 사용되는지 이해하기
문자열의 경우
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);