typescript로 사이드 프로젝트를 진행하면서 코드 리팩토링을 하던 중 partial을 활용하면 코드량을 줄일 수 있을거라는 피드백을 받았다.
타스 공부할 때 partial에 대해서 공부하긴 했었지만, 실제 코드에 적용해본적은 없어서 얼마나 많이 코드량이 줄어들지 기대가 됐다.
먼저, partial에 대해서 다시 한번 알아보자!
Partial
특정 타입에 부분집합의 만족하는 타입을 정의할 수 있다.
type Person {
name: string;
birth: string;
age: number;
}
type Friend = Partial<Person>;
const hans: Friend = {}; // 가능
const harry: Friend = { name: "harry" }; // 가능
const amy: MyEmail = { name: "amy", age: 24 }; // 가능
예시 코드를 보면 알 수 있듯이, Partial<Person> 타입을 가지는 Friend 타입은 Person의 부분집합 값을 모두 수용 가능하다.
기존에 프로젝트에서는 부모 컴포넌트에서 자식 컴포넌트로 값을 업데이트 할 수 있는 함수를 props로 전달중이었는데,
이때 업데이트 되어야 할 속성들이 4개여서 총 4개의 함수를 전달중이었다.
이 부분을 Partial을 사용해서 1개의 함수 전달로 개선 할 예정이다!
아래 타입에 대해서 Partial을 적용 할 예정이다.
type DiscussionFeedData = {
subject1: string;
subject2: string;
content: string;
hashtag: string[];
};
개선 전 부모 컴포넌트
const updateSubject1 = (sub1: string) => {
setDiscussionFeedData((prev) => ({
...prev,
subject1: sub1,
}));
};
const updateSubject2 = (sub2: string) => {
setDiscussionFeedData((prev) => ({
...prev,
subject2: sub2,
}));
};
const updateContents = (newContents: string) => {
setDiscussionFeedData((prev) => ({
...prev,
content: newContents,
}));
};
const updateHashTags = (newHashtags: string[]) => {
setDiscussionFeedData((prev) => ({
...prev,
hashtag: newHashtags,
}));
};
<AddContent
feedType="discussion"
updateContents={updateContents}
updateHashtags={updateHashTags}
updateSubject1={updateSubject1}
updateSubect2={updateSubject2}
/>
개선 전 자식 컴포넌트 <AddContent/>
// props 선언하는 부분
updateContents: (contents: string) => void;
updateHashtags: (hashtags: string[]) => void;
updateSubject1?: (sub1: string) => void;
updateSubject2?: (sub2: string) => void;
// 업데이트 함수 사용하는 부분
useEffect(() => {
updateHashtags(hashtags);
}, [hashtags]);
const onChangeTextarea = (e: ChangeEvent<HTMLTextAreaElement>) => {
updateContents(e.target.value);
};
이렇게 총 4개의 함수를 일일이 전달해주어 코드의 길이가 불필요하게 길어지고 있었다.
이 부분을 Partial로 개선해보았다.
개선 후 부모 컴포넌트
const updateDiscussionFeedData = (
nextDiscussionFeedData: Partial<DiscussionFeedData>,
) => {
setDiscussionFeedData((prev) => ({
...prev,
...nextDiscussionFeedData,
}));
};
<AddContent
feedType="discussion"
updateDiscussionFeedData={updateDiscussionFeedData}
/>
개선 후 자식 컴포넌트
// props 선언 부분
updateDiscussionFeedData: (
nextDiscussionFeedData: Partial<DiscussionFeedData>,
) => void;
// 업데이트 함수 사용하는 부분
useEffect(() => {
updateDiscussionFeedData({ hashtag: hashtags });
}, [hashtags]);
const onChangeTextarea = (e: ChangeEvent<HTMLTextAreaElement>) => {
updateDiscussionFeedData({ content: e.target.value });
};
불필요한 코드량이 많이 줄어들고 4개의 props가 1개로 줄어 가독성도 많이 향상된 것을 볼 수 있다 🥹
partial을 사용해서 개선을 하니 나중에 DiscussionFeedData 타입 구조가 변경되더라도 추가로 update 함수를 생성하지 않아도 돼서
유지보수 측면에서도 훨씬 좋아진 것 같다!