돌멩이 하나/에러는 미래의 연봉

typescript 에러 모음

미래에서 온 개발자 2023. 4. 4. 15:59

1. (TS 2345) Argument of type '...' is not assignable to parameter of type '...'

 

문제 상황: 

광역시/도를 선택하면 해당 시/도에 대한 시/군/구를 select box에 보여줄 수 있게 하는 코드를 작성하려고 했다. 예를 들어 서울을 선택하면 서울의 코드 11000 중 앞의 두 자리 11을 divisionSelectValue라는 상태에 담고, 해당 상태를 useEffect의 종속성 배열에 넣어서 사용자가 시/도 단위의 지역을 선택해서 상태 변경이 일어날 때마다 districtList에 해당 시/도에 대한 시/군/구 데이터를 담으려는 게 목적이었다.

 

지역 1단계 (광역시/도) 선택
지역 2단계 (시/군/구) 선택

// divisions.ts 파일 예시
export const DIVISIONS_DATA = [
  // { code: '0', name: '전국', districts: [] }
  {
    code: '11000',
    name: '서울',
    districts: [
      { name: '강남구', code: '11680' },
      { name: '강동구', code: '11740' },
      { name: '강북구', code: '113050' },
      { name: '강서구', code: '11500' },
      { name: '관악구', code: '11620' },
      { name: '광진구', code: '112150' },
      { name: '구로구', code: '11530' },
      { name: '금천구', code: '115450' },
      { name: '노원구', code: '11350' },
      { name: '도봉구', code: '11320' },
      { name: '동대문구', code: '11200' },
      { name: '동작구', code: '11590' },
      { name: '마포구', code: '11440' },
      { name: '서대문구', code: '11410' },
      { name: '서초구', code: '11650' },
      { name: '성동구', code: '11230' },
      { name: '성북구', code: '11290' },
      { name: '송파구', code: '11710' },
      { name: '양천구', code: '11470' },
      { name: '영등포구', code: '11560' },
      { name: '용산구', code: '11170' },
      { name: '은평구', code: '11380' },
      { name: '종로구', code: '11110' },
      { name: '중구', code: '11140' },
      { name: '중랑구', code: '11260' }
    ]
  },
  // 이하 생략
]
interface DistrictType {
  code: string;
  name: string;
}

  // division: 지역 1단계 (광역시/도)
  // district: 지역 2단계 (시/군/구)
  const [divisionSelectValue, setDivisionSelectValue] = useState('');
  const [districtSelectValue, setDistrictSelectValue] = useState('');
  
  const [districtList, setDistrictList] = useState<DistrictType[]>([]);
  
  useEffect(() => {
    if (divisionSelectValue) {
      setDistrictList(
        DIVISIONS_DATA.find((d) => d.code.startsWith(divisionSelectValue))?.districts
      );
    }
  }, [divisionSelectValue]);

 

에러 메시지:

Argument of type '{ name: string; code: string; }[] | undefined' is not assignable to parameter of type 'SetStateAction<DistrictType[]>'.
Type 'undefined' is not assignalbe to type 'SetStateAction<DistrictType[]>.' 

 

 

에러 원인:

find 메소드를 사용하면 값을 못 찾아서 undefined가 나올 수 있는데, districtList의 타입은 DistrictType[]으로 정해져 있기 때문에 발생한 에러

 

 

해결책:

undefined가 나오지 않을 경우, 즉 find 메소드를 돌린 결과의 값이 있을 경우에만 setState 함수에 넣어주게끔 코드 수정 

  const [districtList, setDistrictList] = useState<DistrictType[]>([]);
  
  useEffect(() => {
    if (divisionSelectValue) {
      const districts = DIVISIONS_DATA.find((d) =>
        d.code.startsWith(divisionSelectValue)
      )?.districts;

      if (districts) setDistrictList(districts);
    }
  }, [divisionSelectValue]);

 

참고:

find 메소드처럼 undefined가 나올 수 있는 경우 뿐 아니라 document.querySelector 처럼 null 이 나올 가능성이 있는 메소드에서도 마찬가지 에러가 발생한다. 

 

 

 

2.  (TS 2749) refers to a value, but is being used as a type here

문제 상황:

styled components 로 작성한 공통 버튼 스타일 컴포넌트를 배경색, width 값 등을 조정할 수 있고, onClick 함수도 props로 받을 수 있는 등 보다 확장성 있는 공통 UI 컴포넌트로 수정하고자 했다. 

// 수정 전
export const S_Button = styled.button`
  color: var(--white);
  background-color: var(--blue300);
  :hover {
    background-color: var(--blue200);
  }
`;

// 수정 후
const StyledButton = styled.button<ButtonStyleType>`
  width: ${(props) => props.width || '100%'};
  background-color: ${(props) => props.backgroundColor || 'var(--blue300)'};
  color: ${(props) => props.color || 'var(--white)'};

  height: 50px;
  padding: 10px 12px;
  border-radius: 5px;
  font-size: 1rem;

  :hover {
    background-color: ${(props) => props.hoverBgColor || 'var(--blue200)'};
  }
`;

interface ButtonStyleType {
  width?: string;
  color?: string;
  backgroundColor?: string;
  hoverBgColor?: string;
}

interface S_ButtonProps {
  children: string;
  addStyle?: ButtonStyleType;
  onClick?: () => void;
}

export function S_Button({ children, addStyle, onClick }: S_ButtonProps) {
  if (addStyle) {
    const { width, backgroundColor, color, hoverBgColor } = addStyle;
    return (
      <StyledButton
        width={width}
        backgroundColor={backgroundColor}
        color={color}
        hoverBgColor={hoverBgColor}
        onClick={onClick}
      >
        {children}
      </StyledButton>
    );
  } else if (onClick !== undefined) {
    return <StyledButton onClick={onClick}>{children}</StyledButton>;
  }

  return <StyledButton>{children}</StyledButton>;
}

 

 

에러 메시지:

(TS2749) refers to a value, but is being used as a type here

 

 

에러 원인:

파일명이 .ts 였다. 스타일 컴포넌트만 있었을 때는 괜찮았지만, JSX를 리턴하는 리액트 컴포넌트를 .ts 파일에 작성하자 해당 오류가 발생하였다.

 

 

해결책:

확장자를 .ts 에서 .tsx로 변경