객체의 Key가 String이 아니라고?
TypeScript를 처음 쓰면 익숙하지 않은 불편한 상황들을 만나게 될 때가 종종 생긴다. 평소처럼 코딩하면 생기는 붉은 줄들을 볼 수 있다. 이번에 만난 문제 또한 그렇다.
Element implicitly has an 'any' type because expression of type 'string' can't be used to index type
TypeScript는 기본적으로 객체의 프로퍼티를 읽을 때, string타입의 key 사용을 허용하지 않는다는 문구의 등장.
나는 분명 JavaScript의 객체의 키값은 Map이 아닌 경우에는 무조건 String만 된다고 알고있었는데.. 이게 무슨 상황?
이런 현상은 단지 이게 TypeScript라서 그렇다는 것이다.
결론적으로 string literal 타입만 허용되는 곳에 string 타입을 사용했기 때문인 것이다.
String과 String Literal의 차이
다음과 같은 TypeScript 코드가 있다. two와 three은 string 타입이 맞지만, one은 "Hello World" 타입이다. Type Script Playground에서 각 변수명에 mouse over하면 타입을 확인할 수 있다.
const one = "Hello World"
let two = "Hello World"
const three: string = "Hello World"
two 변수는 let으로 선언되어 재할당될 수 있을 경우 어떤 문자열이든 넣을 수 있으며 그 경우의 수가 무한대이다. 그렇기 때문에 컴파일러는 이 변수를 string 타입으로 추론한다. 그리고 three 변수는 명시적으로 string 타입으로 선언했으므로 그냥 string 타입이다.
하지만 one의 경우는 조금 이야기가 달라진다. 컴파일러는 이 변수를 string이 아닌 조금 더 좁은 타입(narrowed type)으로 선언한 것으로 추론한다. 이 것을 Literal Narrowing이라고 한다. (참고로 타입 추론은 TypeScript 컴파일러가 제공하는 뛰어난 기능 중 하나이며, 개발자가 명시적으로 타입을 선언해 주지 않을 경우 컴파일러가 할당되는 값을 기준으로 타입을 스스로 결정하는 것을 말한다.)
따라서 one의 타입은 string이 아니라 string타입을 좁혀 만든 string literal type이다. 여기서 "타입을 좁힌다"는 말의 의미는 무한대의 경우의 수를 가질 수 있는 string타입보다 훨씬 구체적인 string의 부분집합, "Hello World"만을 허용하는 타입을 선언했다는 뜻이다.
인용:
https://soopdop.github.io/2020/12/01/index-signatures-in-typescript/
TypeScript에서 string key로 객체에 접근하기
TypeScript에서 string key로 객체에 접근하기
soopdop.github.io
index signature 선언
매번 String Literal로 접근 할 수도 있지만 index signature를 통해 다른 불편한 상황들을 만들지 않고 해결할 수도 있다.
객체의 타입을 정하면서 index signature를 설정해준다. 만드는 방법은 아래와 같다.
type ObjType = {
[index: string]: string
foo: string
bar: string
}
const obj: ObjType = {
foo: "hello",
bar: "world",
}
const propertyName1 = "foo"
const propertyName2: string = "foo"
console.log(obj[propertyName1]) // ok
console.log(obj[propertyName2]) // ok
이 원리로 나도 트러블 슈팅을 해본다.
type ObjType = {
[index: string]: string
고티수상작: string
게임 전체 중에서: string
Y :string
N :string
}
const filterGuide : ObjType= {
고티수상작: "게임 전체 중에서",
"게임 전체 중에서": "고티수상작",
Y: "N",
N: "Y",
};
//filter함수에 적용
setBtnValue([
...arr.filter((e) => e !== filterGuide[key]),
target.innerText,
]);
아주 잘 동작한다!!
'개발이야기' 카테고리의 다른 글
[사이드 프로젝트] 실용주의 프로그래머 한 스푼을 곁들인 포토부스 개발기(n) (1) | 2024.06.30 |
---|---|
Duplicate atom key 에러 메시지 없애기 (Next.js) (0) | 2023.02.26 |
next.js에서 chatGPT api 요청 보내기 ( express.js로 서버 열기 ) (2) | 2023.02.24 |
학습 프레임을 쓰자 [프론트엔드 개발자 취준기] (0) | 2023.02.22 |
next.js에서 순수 css로 reset css하기 (1) | 2023.02.15 |