이런 정의에 타입을 명시하면, 잉여 속성 체크가 동작한다. 잉여 속성 체크는 특히 선택적 속성이 있는 타입의 오타 같은 오류를 잡는데 효과적이다. 변수가 사용되는 순간이 아닌 할당하는 시점에 오류가 표시되도록 해준다.
만약 타입 구문을 제거한다면, 잉여 속성 체크가 동작하지 않는다
→ 객체를 선언한 곳이 아니라 객체가 사용되는 곳에서 타입 오류가 발생한다.
const furby = {
name: 'Furby',
id: 630509430963,
price: 35,
};
logProduct(furby);
// ~~~~~ Argument ... is not assignable to parameter of type 'Product'
// Types of property 'id' are incompatible
// Type 'number' is not assignable to type 'string'
타입 구문을 제대로 명시한다면, 실제로 실수가 발생한 부분에 오류를 표시해준다.
const furby: Product = {
name: 'Furby',
id: 630509430963,
// ~~ Type 'number' is not assignable to type 'string'
price: 35,
};
logProduct(furby);
📍 예시 8 - 함수 반환
함수 반환에도 타입을 명시하여 오류를 방지할 수 있다. 타입 추론이 가능할지라도 구현상의 오류가 함수를 호출한 곳까지 영향을 미치지 않도록 하기 위해 타입 구문을 명시하는 것이 좋다.
주식 시세를 조회하는 함수
function getQuote(ticker: string) {
return fetch(`https://quotes.example.com/?q=${ticker}`)
.then(response => response.json());
}
이미 조회한 종목을 다시 요청하지 않도록 캐시 추가
const cache: {[ticker: string]: number} = {};
function getQuote(ticker: string) {
if (ticker in cache) {
return cache[ticker];
}
return fetch(`https://quotes.example.com/?q=${ticker}`)
.then(response => response.json())
.then(quote => {
cache[ticker] = quote;
return quote as number;
});
}
이 코드에는 오류가 있다.
getQuote;
// ^? function getQuote(ticker: string): number | Promise<number>
getQuote는 항상 Promise를 반환하므로 if 구문에는 cache[ticker]가 아니라 Promise.resolve(cache[ticker])가 반환되도록 해야한다.
실행해보면 getQuote 내부가 아닌 getQuote를 호출한 코드에서 발생한다.
getQuote('MSFT').then(considerBuying);
// ~~~~ Property 'then' does not exist on type
// 'number | Promise<number>'
이 때 의도된 반환 타입(Promise<number>)을 명시한다면, 정확한 위치에 오류가 표시된다.
const cache: {[ticker: string]: number} = {};
function getQuote(ticker: string): Promise<number> {
if (ticker in cache) {
return cache[ticker];
// ~~~ Type 'number' is not assignable to type 'Promise<number>'
}
// ...
}
반환 타입을 명시하면, 구현상의 오류가 사용자 코드의 오류로 표시되지 않는다.
⭐️ 반환 타입을 명시해야 하는 이유
🔗 오류의 위치를 제대로 표시해준다.
🔗 반환 타입을 명시하면 함수에 대해 명확히 알 수 있다.
반환 타입을 명시하려면 구현하기 전에 입력 타입과 출력 타입이 무엇인지 알아야 한다. 추후에 코드가 조금 변경되어도 그 함수의 시그니처는 쉽게 바뀌지 않는다.
미리 타입을 명시하는 방법
→ 함수를 구현하기 전에 테스트를 먼저 작성하는 테스트 주도 개발(test driven development, TDD)과 비슷하다.
전체 타입 시그니처를 먼저 작성하면 구현에 맞추어 주먹구구식으로 시그니처가 작성되는 것을 방지하고 제대로 원하는 모양을 얻게 된다.