Book Review/Effective Typescript
day5_EffectiveTypescript 스터디
예 강
2023. 6. 16. 09:08
2022년 11월 30일 글입니다.
Item18. 매핑된 타입을 사용하여 값을 동기화하기
요약 1: 매핑된 타입을 사용해서 관련된 값과 타입을 동기화 하도록 한다.
- 값을 그대로 때려박는것 보다, 매핑된 타입을 사용하면 함수가 변경되었을 때 참조하고 있던 다른코드에서 알아서 오류를 발생시키기 때문에 유지보수에 용이하다.
- 프로젝트를 유지보수 할 때 우리는 함수를 변경해야 할 때가 많다. 이럴 때 변경된 값을 바로바로 찾을 수 있도록 매핑된 타입을 이용하여 값을 동기화 하자.
- 그러면 함수가 변경되었을 경우 타입체커가 알아서 오류를 발생시켜줘서 유지보수에 용이하다.
예를 들어 산점도를 그리는 인터페이스가 있고 필요할 때만 데이터를 그리기 위해 핸드러를 정의했다고 하자.
interface ScatterProps {
xs: number[];
ys: number[];
xRange: [number, number];
yRange: [number, number];
color: string;
onClick: (x: number, y: number, index: number) => void;
}
function shouldUpdate(oldProps: ScatterProps, newProps: ScatterProps) {
let k: keyof ScatterProps;
for (k in oldProps) {
console.log(k);
if (oldProps[k] !== newProps[k]) {
//같지 않으면 차트를 다시그린다.
if (k !== "onClick") return true;
}
}
}
위와같이 차트가 변경될 때마다 전부 새로 그리는 로직을 보수적 (conservative) 접근법 이자 실패에 닫힌(fail close)
function shouldUpdate(oldProps: ScatterProps, newProps: ScatterProps) {
return (
oldProps.xs !== newProps.xs ||
oldProps.ys !== newProps.ys ||
oldProps.xRange !== newProps.xRange ||
oldProps.yRange !== newProps.yRange ||
oldProps.color !== newProps.color
// (no check for onClick)
);
}
위 코드는 실패에 열린 접근법이라고 한다. 실제로 산점도 전체를 다시 그려야 하는 경우가 있을 수도 있어서 이것도 최적화 코드라고 하기엔 무리가 있다.
그럼 우리는 어떻게 해야할까?
새로운 속성이 추가될 때 직접 shouldUpdate 를 고치게 하는데 이를 타입체커가 알려주게 동기화 해보자 !
interface ScatterProps {
xs: number[];
ys: number[];
xRange: [number, number];
yRange: [number, number];
color: string;
onClick: (x: number, y: number, index: number) => void;
}
const REQUIRES_UPDATE: { [k in keyof ScatterProps]: boolean } = {
xs: true,
ys: true,
xRange: true,
yRange: true,
color: true,
onClick: false,
};
function shouldUpdate(oldProps: ScatterProps, newProps: ScatterProps) {
let k: keyof ScatterProps;
for (k in oldProps) {
if (oldProps[k] !== newProps[k] && REQUIRES_UPDATE) {
return true;
}
}
return false;
}
필요할 때 산점도를 다시 그리게 하는 한편 k 값이 REQUIRES_UPDATE와 다를때 오류가 발생하도록 동기화 시켰다.

이를 위해 REQUIRES_UPDATE가 선언됐으며 만약 데이터 또는 디스플레이 속성이 변경되었을때 이벤트핸들러를 짜고 이와 같은 구조를 사용하는 REQUIRES_UPDATE로 오류를 내도록 동기화 하면, 새로운 속성이 추가됐을 때마다 직접 shouldUpdate함수를 수정하기 용이하다.
- 즉 인터페이스에 새로운 속성을 추가할 때, 선택을 강제하도록 매핑된 타이블 고려해야 한다.