Index Signature
배경
https://velog.io/@huewilliams/unknown-Type 에서 언급했듯, Slate 라이브러리 학습 도중 다음 예제 코드에서 [key: string]: unknown
부분이 이해되지 않아 공부하고 정리하게 되었다.
interface BaseProps {
className: string
[key: string]: unknown
}
처음에는 Array Destructure
문법으로 생각했었는데, 해당 문법인 경우엔 [a,b,c]: [number, number, number]
와 같이 사용하기 때문에 위 코드와 선언과 사용에서 차이가 있었다. 그래서 검색 끝에 Index Signature
문법이라는 것을 알게 되었다.
정리
string과 stringLiteral로 객체 접근
const obj = {
prop: "value"
}
let property = "prop";
console.log(obj[property]); // Error!
JavaScript와 달리 TypeScript는 객체의 프로퍼티를 읽을 때 string
타입의 key 사용을 허용하지 않는다. 따라서 위 코드에서 컴파일 오류가 발생한다.
const a = "Hello World";
let b = "Hello World";
const c: string = "Hello world";
위 예제에서 컴파일러는 a
를 string이 아닌 조금 더 좁은 타입으로 선언한 것으로 추론한다(Literal Narrowing
). a
의 타입은 string 타입보다 구체적인 "Hello World" 타입이다.
b
변수는 let으로 선언되어 어떤 문자열로든 재할당 될 수 있어 컴파일러는 이 변수를 string 타입으로 추론한다.
c
변수는 명시적으로 string 타입으로 선언했으므로 string 타입이다.
이제 처음의 코드를 string literal을 사용하여 정상적으로 컴파일 할 수 있다.
const obj = {
prop: "value"
}
const property = "prop";
console.log(obj[property]); // OK
console.log(obj["prop"]); // OK
String Literal의 유용함
string literal
타입은 열거형 타입처럼 사용할 때 매우 유용하다. 마우스 이벤트를 처리하는 함수가 있을 때, 이벤트 이름을 string
으로 받는다면 오타 혹은 유효하지 않은 이벤트 이름으로 인해 발생하는 런타임에러를 사전에 방지할 수 없다.
function handleEvent(event: string) {}
handleEvent("click");
// 오타나 유효하지 않은 이름이지만 컴파일 타임에 걸러낼 수 없다.
handleEvent("clock"); // Runtime Error!
다음과 같이 string literal
타입 조합을 이용하여 오타를 컴파일 타임에 알 수 있고 IDE의 suggestion 기능도 사용할 수 있다.
type EventType = "mouseout" | "mouseover" | "click";
function handleEvent(evnet: EventType) {}
handleEvent("click");
handleEvent("clock"); // Compile Error!
Index Signature 선언
위에서는 string 키로 객체에 접근할 수 없어서 string literal 키로 대체하여 사용했다. 그러나 Index Signature
를 사용하면 string 키로 객체에 접근할 수 있다.
type ObjType = {
[index: string]: string;
foo: string;
bar: string;
}
const obj: ObjType = {
foo: "hello",
world: "world",
}
const propertyName1 = "foo";
const propertyName2: string = "foo";
console.log(obj[propertyName1]); // ok
console.log(obj[propertyName2]); // ok
Index Signature
선언에서 사용된 index는 Typescript에서 아무 의미가 없으며 가독성을 위해 넣은 내용이다. index가 아닌 어떤 값이 와도 상관없다.
Mapped Type 사용
type AllowedKeys = "hello" | "world";
type ObjType = {
[key in AllowedKeys]: number // OK
}
위와 같이 String 대신 narrowed 타입으로 index signature를 선언하면 오류가 발생한다.
이미 선언된 타입의 프로퍼티에 어떤 조작을 가하여 새로운 타입을 만드는 것을 mapped types
라고 한다.
type AllowedKeys = "hello" | "world";
type ObjType = {
[key in AllowedKeys]: number // OK
}
위 코드는 얼핏 Index Signature
선언과 닮아 보이지만 이 코드는 다음 코드와 완전히 동일하므로 Index Signature
와는 전현 관련 없는 코드이다.
type ObjType = {
hello: number;
world: number;
}
Reference
https://radlohead.gitbook.io/typescript-deep-dive/type-system/index-signatures
https://soopdop.github.io/2020/12/01/index-signatures-in-typescript/
https://velog.io/@yyeonjju/TypeScript-Index-Signature-string-key%EB%A1%9C-%EA%B0%9D%EC%B2%B4%EC%97%90-%EC%A0%91%EA%B7%BC%ED%95%98%EA%B8%B0
Author And Source
이 문제에 관하여(Index Signature), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@huewilliams/Index-Signature저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)