borough.location
배열에 loc
별칭(alias) 생성 예제
const borough = {name: 'Brooklyn', location: [40.688, -79.233]};
const loc = borough.location;
→ 별칭의 값 변경 시 원래 속성값에서도 변경
loc[0] = 0;
borough.location // [0, -79.233]
별칭 남발 시 제어 흐름 분석에 어려움 발생
interface Coordinate {
x: number;
y: number;
}
interface BoundingBox {
x: [number, number];
y: [number, number];
}
interface Polygon {
exterior: Coordinate[];
holes: Coordinate[][];
bbox?: BoundingBox;
}
→ 다각형의 기하학적 구성 : exterior
와 holes
로 구성
→ bbox
: 최적화 속성(옵션)
function isPointInPolygon(polygon: Polygon, pt: Coordinate) {
if (polygon.bbox) {
if (pt.x < polygon.bbox.x[0] || pt.x > polygon.bbox.x[1] ||
pt.y < polygon.bbox.y[0] || pt.y > polygon.bbox.y[1]) {
return false;
}
}
// ...
}
: 잘 동작(타입 체커 통과), 반복되는 부분 존재
→ 중복을 줄이기 위해 임시 변수를 뽑아내는 방법
function isPointInPolygon(polygon: Polygon, pt: Coordinate) {
const box = polygon.bbox;
if (polygon.bbox) {
if (pt.x < box.x[0] || pt.x > box.x[1] ||
// ~~~~~~~~ ~~~~~~~ 객체가 'undefined'일 수 있습니다.
pt.y < box.y[0] || pt.y > box.y[1]) {
// ~~~~~~~~ ~~~~~~~ 객체가 'undefined'일 수 있습니다.
return false;
}
}
// ...
}
// strictNullChecks를 활성화했다고 가정
: 편집기에서 오류로 표시됨
→ polygon.bbox
를 별도의 box
로 별칭했고, 제어 흐름 분석을 방해했으므로
function isPointInPolygon(polygon: Polygon, pt: Coordinate) {
polygon.bbox // BoundingBox | undefined
const box = polygon.bbox;
box // BoundingBox | undefined
if (polygon.bbox) {
polygon.bbox // undefined 정제됨, BoundingBox 타입만 가짐
box // undefined 정제 안됨, BoundingBox | undefined 타입 가짐
}
}
: 오류 발생 원인 : 속성 체크는 polygon.bbox
타입 정제 O, box
타입 정제 X
→ 별칭을 일관성 있게 사용한다는 원칙 지킬 시 방지 가능
box
를 사용하도록 코드 변경 function isPointInPolygon(polygon: Polygon, pt: Coordinate) {
const {bbox} = polygon;
if (bbox) {
const { x, y } = bbox;
if (pt.x < x[0] || pt.x < x[1] ||
pt.y < y[0] || pt.y < y[1]) {
return false;
}
}
// ...
}
bbox
속성이 아닌 x
와 y
가 선택적 속성일 경우 속성 체크가 더 필요 (타입 경계에 null
값 추가) bbox
는 선택적 속성이 적합했으나 holes
는 부적합 holes
가 선택적이라면 값이 없거나 빈 배열([]
)일 것 별칭 : 타입체커 & 런타임에 혼동 야기할 수 있음
const { bbox } = polygon;
if (!bbox) {
calculatePolygonBbox(polygon); // polygon.bbox가 채워지는 함수
// polygon.bbox와 bbox는 다른 값을 참조합니다.
}
function fn (p: Polygon) { /*...*/ }; //polygon.bbox를 제거할 가능성이 있다.
polygon.bbox // BoundingBox | undefined
if(polygon.bbox) {
polygon.bbox // 타입이 BoundingBox
fn(polygon); // polygon.bbox 제거할 가능성 있음
polygon.bbox // 타입이 BoundingBox
}
함수를 호출할 때마다 속성 체크를 반복해야 하기에 좋지 않음
→ TS : 함수가 타입 정제를 무효화하지 않는다고 가정
: 실제로는 무효화될 가능성 존재
polygon.bbox
로 사용하는 대신 bbox
지역변수로 뽑아내 사용하면 bbox
타입은 정확히 유지되나, polygon.bbox
의 값과 같지 않게 유지될 수 있음