Item 16 number 인덱스 시그니처보다는 Array, 튜플, ArrayLike를 사용하기
Object (객체)
자바스크립트에서 객체란 키/값 쌍의 모음이며, 키는 보통 문자열이다. 그리고 값은 어떤 것이든 가능하다.
Python, Java와 달리 '해시 가능 객체'라는 표현이 자바스크립트에는 없다. 만약 복잡한 객체를 사용하려고 하면, toString
메서드가 호출되어 객체가 문자열로 변환된다.
> x = {}
{}
> x[[1, 2, 3]] = 2
2
> x
{ : 1 }
Array (배열)
배열은 객체이다.
> typeof []
'object'
그러니 숫자 인덱스를 쓰는 것이 당연하지만, 인덱스는 문자열로 변환되어 사용되므로, 문자열 키로도 배열의 요소에 접근할 수 있다.
> x = [1, 2, 3]
[1, 2, 3]
> x[0]
1
> x['1']
2
> Object.keys(x)
[ '0', '1', '2' ]
TS는 이러한 혼란을 바로잡고자 숫자 키를 허용하고, 문자열과 다른 것으로 인식한다.
interface Array<T> {
// ...
[n: number]: T
}
런타임에는 ECMAScript 표준이 서술하는 것처럼 문자열 키로 인식하므로, 이 코드는 가상이라고 할 수 있다. 하지만 타입 체크 시점에 오류를 잡을 수 있으므로 유용하다.
const xs = [1, 2, 3]
const x0 = xs[0] // OK
const x1 = xs['1']
// ~~~ 인덱스 식이 'number' 형식이 아니므로 요소에 암시적으로 'any' 형식이 있습니다.
function get<T>(array: T[], k: string): T {
return array[k]
// ~ 인덱스 식이 'number' 형식이 아니므로 요소에 암시적으로 'any' 형식이 있습니다.
}
위 코드는 실제로 동작하지 않는다. 그리고 TS 타입 시스템의 다른 것들과 마찬가지로 타입 정보는 런타임에 제거된다. Item 3 코드 생성과 타입이 관계없음을 이해하기
한편 Object.keys
같은 구문은 여전히 문자열로 반환된다.
const keys = Object.keys(xs) // 타입이 string[]
for (const key in xs) {
key // 타입이 string
const x = xs[key] // 타입이 number
}
string
이 number
에 할당될 수 없으므로 예제의 마지막 줄이 동작하는 것이 동작하는 것이 이상하게 보일 것이다. 배열을 순회하는 코드 스타일에 대한 실용적인 허용이라고 생각하는 것이 좋다. JS에서는 흔하지만 위처럼 순회하는 것은 좋지 않다. 인덱스가 필요한 게 아니라면 for-of를 사용하는 것이 더 좋다.
for (const x of xs) {
x // 타입이 number
}
만약 인덱스의 타입이 중요하다면, number
타입을 제공해 줄 Array.prototype.forEach
를 사용하면 된다.
xs.forEach((x, i) => {
i // 타입이 number
x // 타입이 number
})
루프 중간에 멈춰야 한다면 C 스타일인 for(;;)
루프를 사용하자.
for (let i = 0; i < xs.length; i++) {
const x = xs[i]
if (x < 0) break
}
타입이 불확실하다면, for-in
루프는 for-of
또는 C 스타일 for
루프에 비해 몇 배나 느리다.
어떤 길이를 가지는 배열과 비슷한 형태의 튜플을 사용하고 싶다면 TS의 ArrayLike
타입을 사용한다.
function checkedAccess<T>(xs: ArrayLike<T>, i: number): T {
if (i < xs.length) {
return xs[i]
}
throw new Error(`배열의 끝을 지나서 ${i}를 접근하려고 했습니다.`)
}
ArrayLike
를 사용하더라도 키는 여전히 문자열이다.
Summary
배열은 객체이므로 키는 숫자가 아니라 문자열이다. 인덱스 시그니처로 사용된
number
타입은 버그를 잡기 위한 순수 타입스크립트 코드이다.인덱스 시그니처에
number
를 사용하기보다Array
나 튜플, 또는ArrayLike
타입을 사용하는 것이 좋다.
Last updated
Was this helpful?