[쏙쏙 들어오는 함수형 코딩 Ch14]
update()
- 객체 값 변경하기
incrementQuantity(item)
,incrementSize(item)
… =>incrementField(item, field)
incrementField(item, field)
,decrementField(item, field)
,doubleField(item, field)
… =>update(object, key, modifier)
- 당연히 여기에서도 copy-on-write 활용
update()
활용해 중첩된 객체 값 변경하기
- 재귀 활용
// 책에 있는 JS 코드를 TS/ES6+ 코드로 변환
function nestedUpdate<T = Record<string, unknown>, S = Record<string, unknown>>(
originObject: T,
keys: string[],
modifier: <S>(targetObject: S) => S
): T {
if (keys.length === 0) return modifier(originObject);
const firstKey = keys[0];
const restKeys = dropFirst(keys);
return update(originObject, firstKey, (nestedObjectOfFirstKey) =>
nestedUpdate(nestedObjectOfFirstKey, restKeys, modifier)
);
}
keys에 들어갈 값들을 literal type으로 선언할 수 있을까?
깊이 중첩된 구조에서 주의할 점
기억해야할 것이 너무 많을 때는 추상화 벽을 사용하자
-
중첩된 각 단계에서 기억해야할 새로운 데이터 구조가 있고, 각 구조에 어떤 키가 있는지 기억하기 어려움
-
ex. 블로그 12번째 글에서 글쓴이 이름을 대문자로 바꾸는 경우
-
AS-IS
- 한번에 모든 걸 다 처리
nestedUpdate(blogCatogory, ['posts', '12', 'author', 'name'], capitalize)
-
TO-BE
- 의미 있는 이름을 가진 함수들 만들기
- 어떤 값이 어떤 키에 들어있는지 일일이 기억하지 않아도 되고, 각각의 동작을 기억하기 쉬워짐
type BlogCategory = { /** */ }; type Post = { /** */ }; type User = { /** */ }; function updatePostById( blogCategory: BlogCategory, id: string, modifyPost: (post: Post) => Post ) { return nestedUpdate(blogCategory, ['posts', id], modifyPost); } function updateAuthor(post: Post, modifyUser: (user: User) => User) { return update(post, 'author', modifyUser); } function capitalizeName(user: User) { return update(user, 'name', capitalize); } // 사용 updatePostById(blogCategory, '12', (post) => updateAuthor(post, capitalizeName) );
-
#develop #fp #nested_data