TS에서 객체 순회 시 Type Error 해결하는 방법

박민형·2023년 7월 16일
0
post-thumbnail

독서 모임 개설 및 수정 페이지에서 Form 제작을 맡게 되었다. 모든 정보가 입력이 되어야만 submit 버튼이 활성화 되도록 해야했다. 그러기 위해서는 입력 데이터 객체 순회를 통해 모든 데이터를 check 해야했는데 그 과정에서 발생한 Error 및 해결 방법을 포스팅하려고 한다~

📌 문제 상황

  • checkAllInputData 메소드를 통해 모든 데이터가 있다면 true, 하나의 데이터라도 없다면 false를 return 하도록 구현하였다.
  • 하지만 every 메소드의 매개변수(every((key) => inputDataObj[key]))에서 아래와 같은 Error가 발생하였다
    • Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'GroupFormStateObjProps'. No index signature with a parameter of type 'string' was found on type 'GroupFormStateObjProps' type error
    • 쉽게 말해 GroupFormStateObjProps 타입의 객체를 문자열 key로 조회할 수 없는 문제
  const [isAllInputData, setIsAllInputData] = useState(false);
  const checkAllInputData = (inputDataObj: GroupFormStateObjProps) => {
    return Object.keys(inputDataObj).every((key) => inputDataObj[key]);
  };

  useEffect(() => {
    if (checkAllInputData(classStateObj)) return setIsAllInputData(true);

    isAllInputData && setIsAllInputData(false);
  }, [classStateObj, isAllInputData]);

📌 해결 방법

  • 현재 GroupFormStateObjProps type의 객체는 문자열 key로 조회할 수 없기 때문에 새로운 방법을 생각해야만 했다.
  • 여러 방법을 시도 중에 useEffect에서 얕은 복사를 통해 classStateObj를 참조하는 새로운 객체를 만들고 type을 설정한 후에 전달함으로써 type error 해결할 수 있었다.(checkAllInputData 메소드 매개변수 type도 수정)
  const [isAllInputData, setIsAllInputData] = useState(false);
  const checkAllInputData = (inputDataObj: { [key: string]: string }) => {
    return Object.keys(inputDataObj).every((key) => inputDataObj[key]);
  };

  useEffect(() => {
    const inputDataObj: { [key: string]: string } = {
      ...classStateObj,
    };
    if (checkAllInputData(inputDataObj)) return setIsAllInputData(true);
    
    isAllInputData && setIsAllInputData(false);
  }, [classStateObj, isAllInputData]);
  • 해당 방법은 기존에 classStateObj의 type을 변경하지 않고 데이터 불변성을 유지할 수 있다.
  • 만약 상단의 interface 부분에 새로운 type을 설정하면 classStateObj를 사용하는 다른 곳에서도 type 수정을 해야한다. 하지만 이 방법은 다른 곳에 영향을 주지 않아 가독성 및 유지/보수성을 저하시키지 않는다.

🔎 Object.keys()

  • 주어진 객체의 속성 key를 일반적인 반복문과 동일한 순서로 순회되는 열거할 수 있는 배열로 반환
const object1 = {
  a: 'somestring',
  b: 42,
  c: false
};

console.log(Object.keys(object1));
// Expected output: Array ["a", "b", "c"]

🔎 every, some 메소드

every

  • 배열의 모든 요소가 주어진 콜백 함수를 실행했을 때 true를 반환하면 everytrue를 반환하고, 그렇지 않으면 false를 반환
  • 배열의 모든 요소가 조건을 만족하지 않으면 나머지 요소를 검사하지 않고 즉시 false를 반환하며, 배열이 비어있는 경우에는 항상 true를 반환
const numbers = [1, 2, 3, 4, 5];

const allEven = numbers.every((num) => num % 2 === 0);
console.log(allEven); // false

const allPositive = numbers.every((num) => num > 0);
console.log(allPositive); // true

some

  • 배열의 요소 중에서 하나라도 주어진 콜백 함수를 실행했을 때 true를 반환하면 sometrue를 반환하고, 그렇지 않으면 false를 반환
  • 배열의 모든 요소를 검사하지 않고, 조건을 만족하는 요소를 찾으면 즉시 true를 반환하며, 배열이 비어있는 경우에는 항상 false를 반환
const numbers = [1, 2, 3, 4, 5];

const hasEven = numbers.some((num) => num % 2 === 0);
console.log(hasEven); // true

const hasNegative = numbers.some((num) => num < 0);
console.log(hasNegative); // false

📌 결론

type Error가 발생했을 때 적잖게 당황했었는데 Error 발생 이유를 이해함으로써 문제를 해결할 수 있었다. TS에서 이런 Error가 자주 발생하는 것에 있어 조금 번거롭기는 하지만 현재 뿐만 아니라 미래에 유지/보수 및 잠재적인 Error를 방지하는데 많은 도움이 된다고 생각한다. TS에 대해서 조금더 고민하고 학습을 해야할 것 같다.

0개의 댓글