넓히기 과정 제어하는 방법
- const
- let 대신 const로 변수를 선언하면 더 좁은 타입이 된다.
const x = 'x'; let vec = {x: 10, y: 20, z: 30}; getComponent(vec, x); x 는 재할당 될 수 없기 때문에 ⇒ 더 좁은 타입 (”x”)로 추론할 수 있다.
타입 추론의 강도를 직접 제어하려면
⇒ 타입스크립트의 기본 동작을 재정의해야
- 명시적 타입 구문 제공
- 타입 체커에 추가적인 문맥 제공
- const 단언문 사용 (const 단언문과 변수 선언에 쓰이는 let 이나 const와 혼동 x)
const v1 = { x: 1, y: 2, }; // 타입은 { x: number; y: number; } const v2 = { x: 1 as const, y: 2, }; // 타입은 { x: 1; y: number; } const v3 = { x: 1, y: 2, } as const; // 타입은 { readonly x:1, readonly y: 2; }
넓히기로 인해 오류 발생된다 생각되면, 명시적 타입 구문 또는 const 단언문을 추가하는 것을 고려해야 한다.
타입 좁히기
: 타입스크립트가 넓은 타입으로부터 좁은 타입으로 진행하는 과정
- null 체크
- 분기문 예외 throw
- instanceof 사용
- 속성체크
- Array.isArray 같은 일부 내장 함수
- 명시적 ‘태그’ 부여
⇒ ‘태그된 유니온’ 또는 ‘구별된 유니온’ 이라고 함
- 커스텀 함수 도입
⇒ ‘사용자 정의 타입 가드’ 라고 함
타입스크립트의 변수 ⇒ 변경
타입스크립트의 타입 ⇒ 변경 x
⇒ 때문에 일부 자바스크립트 패턴을 타입스크립트로 모델링 쉬움
⇒ 속성을 하나씩 추가보다, 여러 속성을 포함해 객체를 한번에 생성해야 ⇒ 타입 추론에 유리
const pt = {}; pt.x = 3; pt.y = 4;
- 자바스크립트에서는 가능
- 타입스크립트에서는 각 할당문에 오류 발생
// ~ '{}' 형식에 'x' 속성이 없습니다.
Point 인터페이스 정의하면 이런 오류로 바뀜
interface Point { x: number, y: number; } const pt: Point = {}; // ~~ '{}' 형식에 'Point' 형식의 x, y 속성이 없습니다. pt.x = 3; pt.y = 4; 객체를 한 번에 정의하면 해결할 수 있다.
const pt = { x: 3, y: 4, };
작은 객체들을 조합해 큰 객체를 만들어야 하는 경우 ⇒ ‘객체 전개 연산자’ 사용
{…a, …b}
별칭 사용은 주의하자
- 남발 사용 ⇒ 제어 흐름 분석 어렵다.
interface Coordinate { x: number; y: number; } interface BoundingBox { x: [number, number]; y: [number, number]; } interface Polygon { exterior: Coordinate[]; holes: Coordinate[][]; bbox?: BoundingBox; } function isPointInPolygon(polygon: Polygon, pt: Coordinate) { const box = polygon.bbox; if (polygon.bbox) { if (pt.x < box.x[0]) { // 객체가 'undefined'일 수 있습니다. } } }
polygon.bbox // 타입이 BoundingBox | undefined const box = polygon.bbox; box // 타입이 BoundingBox | undefined if (polygon.bbox) { polygon.bbox // 타입이 BoundingBox box // 타입이 BoundingBox | undefined }
속성 체크는 polygon,.bbox의 타입을 정제했지만 box는 그렇지 않았기 때문에 오류가 발생했다.
이러한 오류는 "별칭은 일관성 있게 사용한다"
는 기본 원칙(golden rule)을 지키면 방지할 수 있다.
타입 체커의 문제는 해결되었지만 box와 bbox는 같은 값인데 다른 이름을 사용하였다.
이는 비구조화 문법을 이용하면 간결한 문법으로 일관된 이름을 사용할 수 있다.
function isPointInPolygon(polygon: Polygon, pt: Coordinate) { const {bbox} = polygon; if (bbox) { if (pt.x < bbox.x[0]) { // 정상, bbox 타입은 BoundingBox } } }
주의해야할 점
별칭은 타입 체커 뿐만 아니라 런타임에도 혼동을 야기할 수 있다.
const {bbox} = polygon; if(!bbox) { calculatePoygonBbox(polygon); // polygon.bbox가 채워짐 // 이제 polygon.bbox와 bbox는 다른 값을 참조하게 됨 }
- 별칭은 타입스크립트가 타입을 좁히는 것을 방해한다.
- 따라서 변수에 별칭을 사용할 때는 일관되게 사용해야 한다.
- 비구조화 문법을 사용해서 일관된 이름을 사용하는 것이 좋다.
- 함수 호출이 객체 속성의 타입 정제를 무효화할 수 있다는 점을 주의해야한다.
- 속성보다 지역 변수를 사용하면 타입 정제를 믿을 수 있다.
비동기 코드
- 콜백 중첩 ⇒ 직관적 이해 어렵다
Uploaded by N2T
'Front-End' 카테고리의 다른 글
[서평] Do it! 리액트로 웹앱 만들기 with 타입스크립트 - 후기 (0) | 2024.04.09 |
---|---|
[React] 리액트란 무엇인가요? (1) | 2024.01.23 |
[TypeScript] 17. 변경 관련된 오류 방지를 위해 readonly 사용하기 (0) | 2023.07.26 |
[React] 리액트 공식문서 스터디 - Describing the UI (2) Importing and Exporting Components (0) | 2023.07.26 |
[React] 리액트 공식문서 스터디 - Describing the UI (1) Your First Component (0) | 2023.07.26 |