개인 프로젝트를 진행하다가 string
이 담긴 배열을 순회해서 string
을 키로 객체에 접근하려다가 문제가 발생했다.
객체안의 원하는 데이터는 렌더링이 되긴하지만 문제는 타입스크립트에서 화를 낸다는 것이다..😢
타입스크립트를 달래주기 위해 구글링을 시작했다.
일단 TypeScript는 기본적으로 객체의 프로퍼티를 읽을 때
string
타입의key
사용을 허용하지 않는다고 한다.
String
은 내장된 타입으로, 문자열을 나타내는 데 사용된다.
let str: string = "Hello"; // string 타입
String Literal
은 특정한 값을 가지는 문자열을 나타내는 타입이다. 즉, 문자열 값 자체가 타입의 일부가 된다. String Literal
타입은 문자열 값을 제한하여 특정한 값만을 수용한다. 이를 위해 string
키워드 대신 문자열 값을 직접 지정한다.
let literal: "Hello" = "Hello"; // "Hello"라는 문자열 리터럴 타입
위에서 literal
변수는 "Hello"
라는 문자열 리터럴 타입으로 선언되어 있다. 이는 문자열 값이 "Hello"
로 제한되고, 다른 값은 허용되지 않는다는 의미다. 즉, literal
변수에 다른 문자열 값을 할당하려고 하면 타입 에러가 발생한다.
일단 타입이 달라서 안된다는 이유는 알았다. 그렇다면 어떻게 해결해야 하는가?
해당 객체에 Index Signature를 추가하면 된다고 한다.
type objType = {
[key: string]: string;
}
???? 중복된 선언이라고 한다.
당연히 각자 키가 다르기 때문에 따로 선언해주어야 한다고 생각했는데, 타입스크립트에서 객체의 타입을 수정하면 해당 타입이 사용되는 모든 곳에 영향을 미친다고 한다. 따라서 첫 번째 객체만 수정해도 모든 객체에 영향을 미치는 것이 정상적인 동작이다.
type objType = {
[key: string]: string;
foo: string;
bar: string;
}
이런 식으로 Index Signature를 선언하면 foo
와 bar
도 string
인덱스로 접근할 수 있다.
Index Signature를 number 타입으로 선언하면 다음과 같이 배열 literal 방식으로 할당도 가능하다.
type objType = {
[key: number]: string;
}
const obj: objType = {
0: "hi",
1: "hello"
};
console.log(obj[0], obj[1]) // "hi" "hello"
둘이 함께 사용했을 경우 가능은 하지만 이 경우 배열 literal 방식의 할당은 불가능 하다고 한다.
type ArrayLikeType = {
[key: number]: string;
[key: string]: string;
}
let obj: ArrayLikeType = {
0: "hello",
foo: "world",
} // ok.
let foo = "foo"
console.log(obj[0], obj[foo]) // "hello" "world"
obj = ["hello", "world"] // compile error!
참고
TypeScript | Index Signature - string key로 객체에 접근하기
TypeScript에서 string key로 객체에 접근하기