16. number 인덱스 시그니처 대신

ClassBinu·2024년 4월 16일

number 인덱스 시그니처보다는 Array, 튜플, ArrayLike를 사용하기

배열은 객체이다. 즉, 키는 숫자가 아니라 문자열이다.
자바스크립트에서 배열은 사실상 숫자 인덱스를 사용하는 객체이다. 그래서 키는 '문자열'로 변환된다.

자바스크립트.. 뭐 하세요?

let array = [];
array[0] = "hello";  // 숫자 인덱스
array['1'] = "world";  // 문자열 인덱스, 숫자로 해석
array['key'] = "value";  // 일반 객체의 키

console.log(array);  // ["hello", "world", key: "value"]
console.log(array.length);  // 2, "key"는 length에 영향을 주지 않음

타입스크립트가 해결한다!

숫자 키를 허용하고, 문자열 키와 다른 것으로 인식!

자바스크립트에서 배열은 사실 객체다.
이걸 타입스크립트에서는 배열과 일반 객체를 구분한다.

타입스크립트는 배열에 접근할 때 숫자 인덱스를 사용하도록 강제한다!

// lib.es5.d.ts에 선언
interface Array<T> {
  //..
  [n: number]: T;
}
let numbers: number[] = [1, 2, 3]; // 배열
let user: { [key: string]: any } = { name: "John", age: 30 }; // 일반 객체

console.log(numbers.length); // 3
console.log(user.length); // undefined, 객체는 length 속성이 없습니다.

왜 문자열 인덱스도 허용해?

분명히 타입스크립트는 숫자 인덱스만 허용한다고 하는데, 문자도 허용한다.

숫자로 변환 가능한 문자는 인정한다!!

하지만 숫자로 변환 가능한 문자열 키는 자바스크립트와의 호환성을 유지하기 위해 허용됩니다.

타입스크립트가 배열에 문자열 인덱스를 사용할 때 오류를 발생시키지 않는 것은, 그 문자열이 숫자로 해석될 수 있는 경우에 한정됩니다. 그러나 일반적으로 배열과 함께 문자열 인덱스를 사용하는 것은 권장되지 않으며, 이는 코드의 가독성과 유지보수성을 저해할 수 있습니다.

let numbers: Array<number> = [1, 2, 3];

numbers["result"] = 5; // 에러 발생
numbers["0"] = 5; // 이건 허용

console.log(numbers);

// TSError: ⨯ Unable to compile TypeScript:
// t16.ts:3:9 - error TS7015: Element implicitly has an 'any' type because index expression is not of type 'number'.

// 3 numbers["result"] = 5;

만약 자바스크립트였다면 에러 발생 안 함.

let numbers = [1, 2, 3];

numbers["result"] = 5; // 이것도 정상 실행
numbers["0"] = 5; // 이건 허용

console.log(numbers);

타입 체크만 하는거임. 런타임에서 여전히 자바스크립트 엔진에서 작동함! 즉, 결국 변환되면 내부적으로는 키는 문자열로 사용됨.

ArrayLike

배열 유사 객체
배열처럼 인덱스로 접근 가능
length 속성 가짐

표준 라이브러리에 정의

interface ArrayLike<T> {
    readonly length: number;
    [index: number]: T;
}

사용 예시

function logArguments() {
    let args: ArrayLike<any> = arguments;
    console.log(args.length);  // 인자의 개수를 출력
    console.log(args[0]);      // 첫 번째 인자를 출력
}

logArguments(10, 20, 30);  // 출력: 3, 10

0개의 댓글