넓히기 과정 제어하는 방법
- 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 |