줍줍 프로젝트는 슬랙 메시지를 아카이빙하는 서비스입니다.
프로젝트 github
리액트 & 타입스크립트를 사용한다면 props로 children을 내려주고 children의 타입을 설정해 주는 경험을 해보신 적이 있을 것이다.
children의 타입을 설정할 때 여러분들은 어떻게 타입을 선언해주시나요?!
아래 코드처럼 children에 ReactNode를 직접 명시하는 방법입니다.
interface Props {
isOpened: boolean;
handleCloseModal: () => void;
children: ReactNode;
}
function Modal({ isOpened, handleCloseModal, children }: Props) {
return (
<Portal isOpened={isOpened}>
<>
<Dimmer hasBackgroundColor={true} onClick={handleCloseModal} />
{children}
</>
</Portal>
);
}
PropsWithChildren 타입을 사용하게 되면 반복적으로 children 타입을 설정해줘야하는 번거로움이 사라질 수 있습니다.
interface Props {
isOpened: boolean;
handleCloseModal: () => void;
}
function Modal({
isOpened,
handleCloseModal,
children,
}: PropsWithChildren<Props>) {
return (
<Portal isOpened={isOpened}>
<>
<Dimmer hasBackgroundColor={true} onClick={handleCloseModal} />
{children}
</>
</Portal>
);
}
그럼 PropsWithChildren 타입은 어떻게 작성되어 있는지 d.ts 파일을 확인해보겠습니다.
type PropsWithChildren<P = unknown> = P & { children?: ReactNode | undefined };
PropsWithChildren의 children 타입이 옵셔널인 것을 확인할 수 있습니다.
여기서 의문을 가지게 되었는데,
라는 의문이였습니다.
당연한 결과일 수 있겠지만, 혹시 몰라 Modal 컴포넌트를 사용하는 곳에서 children을 넘겨주지 않고 사용해봤지만, 에러는 띄워지지 않는 것을 확인할 수 있다.
따라서, PropsWithChildren을 사용해야하는 경우 children을 옵셔널로 사용할 경우에만 사용하고, 항상 children을 넘겨줘야하는 경우에는 PropsWithChildren을 사용하지 않는게 좋다는 결론을 내리게 되었습니다.
그렇다면 처음에 설명한 것과 같이 children의 타입을 매번 ReactNode 설정해주는 방법도 있겠지만, 저희는 PropsWithChildren과 같은 StrictPropsWithChildren 유틸 타입을 만들어 반복되는 작업을 줄이고자 했습니다.
export type StrictPropsWithChildren<P = unknown> = P & {
children: ReactNode;
};
PropsWithChildren과 거의 동일한 유틸 타입이지만 children에 옵셔널을 제거함으로써 children을 넘겨주지 않을 경우 에러가 띄워질 수 있도록 설정했습니다.
이번에 PropsWithChildren 유틸 타입을 살펴보며서 리액트 혹은 라이브러리에서 기본적으로 제공해주는 타입이더라도 한 번 더 살펴보고 현재 사용하고자 하는 곳에서 타입이 안전하지 않다고 느껴진다면 조금 더 안전한 타입을 새롭게 설계해 사용함으로써 개발자의 실수를 줄일 수 있다는 것을 알게 되었습니다.
끗.
좋은 글 감사합니다!