[TS] reduce

장동균·2022년 2월 23일
0
const EmptyObject = {}

const EmptyArray = []

EmptyObject[0] = '111'
EmptyArray[1] = '111'

자바스크립트에서는 빈 객체, 빈 배열에 대한 할당이 문제없이 동작한다. 하지만, 타입스크립트에서 이 둘은 차이점을 가진다.

사진에서 확인할 수 있듯이, 빈 객체를 할당하는 경우 type은 {}, 빈 배열을 할당하는 경우 type은 any[]가 된다. 이러한 차이로 인해 값을 할당할 때에도 차이가 생긴다.

const EmptyObject = {}

const EmptyArray = []

EmptyObject[0] = '111'  // Error: Property '0' does not exist on type {}
EmptyArray[1] = '111'  // OK

때문에 빈 객체를 사용하는 경우 명시적인 타임 선언이 필요하다.

const EmptyObject: Record<number, string> = {}

EmptyObject[0] = '111'  // OK
EmptyObject[1] = '111'  // OK
EmptyObject[2] = '111'  // OK
EmptyObject[100] = '111'  // OK

빈 객체를 사용하게 되는 경우가 또 언제 있을까? 바로 reduce를 사용할 때이다! reduce의 accumulator 초기값을 빈 객체로 선언한다면 위에서 발생한 문제를 다시 확인할 수 있다.

const numberArr = [1, 2, 3, 4, 5, 6, 7]

const sum = numberArr.reduce((acc, curr, idx) => {
  	// Error: No index signature with a parameter of type 'number' was found on type '{}'.
    acc[idx] = curr
    return acc
}, {})

때문에 reduce의 accumulator로 빈 객체를 사용해야하는 경우 accumulator에 대한 명시적인 타입 선언이 필요하다. 이는 reduce에 제네릭 인자를 넘기는 것으로 가능하다.

const numberArr = [1, 2, 3, 4, 5, 6, 7]

const sum = numberArr.reduce<Record<number, number>>((acc, curr, idx) => {
  	// OK: 암시적으로 추론된 {}가 acc에 대한 타입으로 사용되는 것이 아닌, 명시적으로 추론된 Record<number, number>가 사용되었다.
    acc[idx] = curr
    return acc
}, {})

의문점

reduce의 accumulator로 빈 배열을 사용하면 어떨까?
=> 에러가 난다. 기존의 실험대로라면 any[] 타입이 되고, 에러 없이 정상적으로 수행되어야 한다. 하지만 실제 타입을 확인해보면 never[]가 되어 있는 것을 확인 할 수 있다. never[]이기 떄문에 값을 할당했을 때 에러가 난다. 확실한 것은 아니지만 아마도 reduce 함수 내부에서 never[]를 뱉어내는 것 같다.


결론

빈 객체를 쓴다면 반드시 객체의 타입을 명시적으로 정의해두고 넘어가자!!!

profile
프론트 개발자가 되고 싶어요

0개의 댓글