본문 바로가기

프로젝트 개발일지/TIFY

타입 가드로 해결한 Array.map is not a function 에러

map 함수를 사용하다 보면 진짜 자주 나타나는 에러가 하나 있다.

Array.map is not a function

이라는 에러인데, 이번에 또 나타나버렸다.
 
현재는 map 함수 앞에 적힌 변수가 undefined이거나 배열일 수 있다.
그래서 map 함수가 에러를 내는 것이다.
 
그런데, 갑자기 이 예시가 떠올랐다.
이펙티브 타입스크립트를 읽으며 가장 기억에 남는 예시였다.

const members = ['janet', 'michael'].map(who => jackson5.find(n => n === who));  // 타입이 (string|undefined)[]

const members = ['janet', 'michael'].map(who => jackson5.find(n => n === who).filter(who => who !== undefined);  // 타입이 (string|undefined)[]

function isDefined<T>(x: T | undefined): x is T {
	return x !== undefined;
}

const members = ['janet', 'michael'].map(who => jackson5.find(n => n === who).filter(isDefined);  // 타입이 string[]

 
이 예시는 물론 배열 요소들 중 undefined가 없도록 타입 가드 함수를 사용해서 필터 해주는 것이 목적이었다.
필터 함수를 사용하지 않았을 때는 members 배열의 타입이 (string | undefined)[]로 나타났었다.
그런데, 필터 함수타입 가드 함수를 도입하니 string[]로 잘 필터 된 것을 볼 수 있었다.
 
나도 그래서, map 함수에서 나타나는 에러를 타입 가드를 사용해서 해결해 보았다.
타입 가드를 통해서 undefined인 경우를 거르고 배열만을 남겨보려 했다.
 
아래와 같이 타입 가드 함수를 작성해 주었다.

const isArray = (
    arr: unknown[] | undefined,
  ): arr is unknown[] => {
    return Array.isArray(arr)
  }
{isArray(rightChildrenIcon)
  ? rightChildrenIcon.map((icon, index) => (
    <div key={index}>{icon}</div>
  ))
  : null}

이렇게 하니, 이전에 나타났던 map 관련 에러가 없어졌다.

 

물론 Array 내장 함수 Array.isArray를 써도 된다.

하지만 단순히 Array.isArray의 내부 구현은 모르고 사용만 해보는 것보다 이렇게 타입스크립트를 활용해서 isArray 함수를 작성해봐서 타입 가드에 대해서도 확실하게 이해할 수 있었다.
 
사실 이전까지는 타입 가드에 대한 크게 와닿는 예시가 없어서 그런지 쓸 필요성을 못 느꼈었는데, 위 예시를 통해서 어떤 상황에 써야 할지 알게 된 거 같다.
타입 가드도 필요한 상황에 맞춰서 잘 활용해 봐야겠다.