-
이펙티브 타입스크립트- 3장 타입추론 (4)TypeScript 2022. 4. 18. 20:55
아이템 24. 일관성 있는 별칭 사용하기
객체의 프로퍼티를 코드 내에서 간결하게 사용하기 위해 별칭(Alias)을 추가하는 경우, 일관되지 않은 이름으로 혼란을 줄 수 있다.
function isPointInPolygon(polygon: Polygon, pt: Coordinate) { const box = polygon.bbox; // bbox, box라는 서로 다른 이름이 쓰이고 있다. if (box) { // ... } }
일관된 이름을 사용하기 위해서는 구조분해 할당(destructuring)을 사용하는 것이 좋다. 단, 여전히 별칭을 사용하고 있기 때문에, polygon.bbox와 지역변수 bbox의 타입은 같더라도 값은 서로 달라질 수 있다는 점을 알아두자.
function isPointInPolygon(polygon: Polygon, pt: Coordinate) { const { bbox } = polygon; if (bbox) { // ... } }
요약
- 별칭은 타입스크립트가 타입을 좁히는 것을 방해한다. 따라서 변수에 별칭을 사용할 때는 일관되게 사용해야 한다.
- 새로운 변수 별칭 보다는 객체 비구조화를 고려하자
- 함수 호출이 객체 속성의 타입 정제를 무효화할 수 있다는 점을 주의해야 한다. 속성보다 지역 변수를 사용하면 타입 정제를 믿을 수 있다.
아이템 25. 비동기 코드에는 콜백 대신 async 함수 사용하기
비동기 함수를 작성할 때 콜백보다는 프로미스, 프로미스보다는 async/ await를 사용해야 하는 것이 코드 작성과 타입 추론을 쉽게 한다.
ES2015이전에는 비동기 동작을 위해 콜백을 사용했고 이는 콜백지옥 필연적으로 낳았다.
하지만 ES2015의 Promise와 ES2017의 async/await 덕분에 비동기 코드의 가독성을 크게 개선되었다.
// 병렬적으로 페이지를 로드하고 싶은 경우 async function fetchPages() { const [response1, response2, response3] = await Promise.all([ fetch(url1), fetch(url2), fetch(url3) ]); // ... } // 처음으로 처리된 프로미스가 생겼을 때 완료하고 싶은 경우 async function fetchPages() { const [response1, response2, response3] = await Promise.race([ fetch(url1), fetch(url2), fetch(url3) ]); // ... } // 타임아웃 추가하기 function timeout(ms: number): Promise<never> { return new Promise((resolve, reject) => { setTimeout(() => reject('timeout'), ms); }); } async function fetchWithTimeout(url: string, ms: number) { return Promise.race([fetch(url), timeout(ms)]; }
위에서 fetchWithTimeout은 리턴값의 타입을 명시하지 않아도 Promise<Response>로 타입이 잘 추론된다. Promise.race의 반환타입은 입력 타입들의 유니온이다. fetch(url)은 Promise<Response>, timeout(ms)는 Promise<never> 타입을 반환하기 때문에 Promise<Response | never>가 되고, never가 공집합이기 때문에 결국 Promise<Response>가 되는 것이다.
일반적으로 프로미스를 생성하기 보다 async/await를 사용해야 하는 이유는
- 더 간결하고 직관적인 코드가 된다.
- async 함수는 항상 프로미스를 반환하도록 강제한다.
const getNumber = async () => 42; // 타입이 () => Promise<number>
함수는 항상 동기 또는 비동기로 실행되어야 하며 절대 혼용해서는 안된다.
async 함수에서 프로미스를 반환하면 또 다른 프로미스로 래핑되지 않는다. 반환 타입은 Promise<Promise<T>>가 아닌 Promise<T>가 된다. 타입스크립트를 사용하면 타입 정보가 명확히 드러나기 때문에 비동기 코드의 개념을 잡는데 도움이 된다.
// function getJSON(url: string): Promise<any> async function getJSON(url: string) { const response = await fetch(url); const jsonPromise = response.json(); // 타입이 Promise<any> return jsonPromise;
요약
- 콜백보다는 프로미스를 사용하는 게 코드 작성과 타입 추론 면에서 유리하다
- 프로미스보다는 async와 await를 사용하는게 간결하고 직관적 코드를 작성하여 오류를 제거하기 쉽다.
- 어떤 함수가 프로미스를 반환한다면 async로 선언하는 것이 좋다.
'TypeScript' 카테고리의 다른 글
이펙티브 타입스크립트- 4장 타입설계 (1) (0) 2022.04.24 이펙티브 타입스크립트- 3장 타입추론 (5) (0) 2022.04.23 이펙티브 타입스크립트- 3장 타입추론 (3) (0) 2022.04.17 이펙티브 타입스크립트- 3장 타입추론 (2) (0) 2022.04.10 이펙티브 타입스크립트- 3장 타입추론 (1) (0) 2022.04.03