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[]
를 뱉어내는 것 같다.
빈 객체를 쓴다면 반드시 객체의 타입을 명시적으로 정의해두고 넘어가자!!!