문제
다음과 같은 모달 버튼들을 모아놓은 컨테이너를 만들던 도중 고민이 생겼다.
모달 버튼에
isConfirm
이라는 확인 버튼에 대한 여부를 boolean값으로 받는 버튼의 props를 생성해야 했는데, 기존 intrnisicAttributes
에 없는 속성이라고 내뱉는 것.이를 어떻게 해결해야 할까? 코드는 다음과 같다.
import styled from '@emotion/styled'; import React from 'react'; import styles from '@styles/index'; import { css } from '@emotion/react'; export interface ModalButtonsProps { modalType: string; width: string | number; onConfirm?: () => void; onClose: () => void; } const Button = styled.button` width: 80px; height: 32px; margin: 0 16px; font-size: ${styles.fontSize.small}; font-weight: 700; background: transparent; border: 0; border-radius: 16px; ${({ modalType }) => css` color: ${modalType === 'default' ? styles.colors.point : styles.colors.warning}; border: 2px solid ${modalType === 'default' ? styles.colors.point : styles.colors.warning}; `} ${({ modalType, onConfirm }: Partial<ModalButtonsProps>) => onConfirm && css` color: ${modalType === 'default' ? styles.colors.point : styles.colors.background}; background: ${modalType === 'default' ? styles.colors.point : styles.colors.warning}; `}; `; const StyledModalButtons = styled.div` position: absolute; bottom: 30px; box-sizing: border-box; display: flex; justify-content: center; margin: 0 auto; `; const ModalButtons = ({ modalType = 'default', onClose, onConfirm, }: ModalButtonsProps) => { return ( <StyledModalButtons> {onConfirm && ( <Button modalType={modalType} onClick={onConfirm} isConfirm> 예 </Button> )} <Button modalType={modalType} onClick={onClose}> 아니오 </Button> </StyledModalButtons> ); }; export default ModalButtons;
해결
해당 이모션 공식 문서를 참조하면서 타입에 대해 좀 더 고민하기 시작했다.
여기서는,
React.FC
를 CSS-in-JS에 명시해주면 된다고 했다.따라서 다음과 같이 수행하였다.
export interface ButtonProps { isConfirm: boolean; }
그러자,
'{ children: string; modalType: string; onClick: () => void; }' 형식은 'IntrinsicAttributes & ButtonProps & { children?: ReactNode; }' 형식에 할당할 수 없습니다. 'IntrinsicAttributes & ButtonProps & { children?: ReactNode; }' 형식에 'modalType' 속성이 없습니다.
라는 오류가 발생했다.
음... 아무래도 기존
ModalButtonProps
에서 타입을 상속받아야 할 듯 싶다.그런데 이상하다.
ModalButtonProps
에서 ModalButtons
를 상속한다?사실 가장 추상성이 높은 건
Button
인데 말이다.자고로 인터페이스의 확장은 열려있지만, 수정은 닫혀있어야 한다.
그렇지만, 현재의 경우
onClick
을 강제로 ModalButtonProps
에 순수하게 넘겨줄 수 있는 방안이 없다.따라서 다음과 같이 리팩토링하였다.
export interface ButtonProps { isConfirm?: boolean; modalType: string; onClick: () => void; } export interface ModalButtonsProps extends Partial<ButtonProps> { width: string | number; onConfirm: () => void; onClose: () => void; }
이제 가장 추상성 높은
ButtonProps
를 상속 받음으로써 좀 더 유연한 구조가 되었다.이후, 다음과 같이 수정한다.
${({ modalType }: ButtonProps) => css` color: ${modalType === 'default' ? styles.colors.point : styles.colors.warning}; border: 2px solid ${modalType === 'default' ? styles.colors.point : styles.colors.warning}; `} ${({ modalType, isConfirm }: ButtonProps) => isConfirm && css` color: ${modalType === 'default' ? styles.colors.point : styles.colors.background}; background: ${modalType === 'default' ? styles.colors.point : styles.colors.warning}; `};
결과
문제가 발견되지 않는다.

또한, 스토리북 역시 잘 동작한다!
