타입 챌린지 1367 - Remove Index Signature

소파의 벨로그·2025년 4월 2일

타입챌린지

목록 보기
42/131

문제 링크

문제

객체 유형에서 인덱스 시그니처를 제외하는 RemoveIndexSignature<T>를 구현하세요


정확하게는 string|number|symbol이 인덱스 시그니쳐

내 풀이

type RemoveIndexSignature<T> = {
  [R in keyof T as string extends R?
  				never
  				:number extends R?
  					never
  				:symbol extends R?
  					never
  				:R]:T[R]
}

만약 R이 index-signiture라면, string extends R,number extends R,symbol extends R 중 하나가 true가 나오므로 키에 never를 주고, 그렇지 않다면 키에 R을 줘서 사용한다.

다른 사람의 풀이

type RemoveIndexSignature<T, P=PropertyKey> = {
  [K in keyof T as P extends K? never : K extends P ? K : never]: T[K]
}

이런 풀이도 있었다.

PropertyKey는 string | number | symbol이다.
참고로 분배법칙에 의해 string,number,symbol 타입이 mapped type의 key 타입에 있는 P에 각각 들어간다

P가 K를 확장하는 경우가 never이다.
P와 K를 확장하는 경우는 stringstring과 같이 시그니쳐 타입이므로 이를 제거해주는 작업이다.

P가 K를 확장하지 않는 경우를 살펴볼 수 있다.
1) 두 타입이 완전히 다른 경우 (P는 number, K는 string)
2) 두 타입이 겹치고, K가 P를 확장하는 경우 (P는 number, K는 1)

이때, 경우 2)에서만 K를 추출하려고 한다.
왜냐하면 경우 1)은 K를 검사하기 위해서 별로 필요없는 상황이기 때문이다.

이제 K extends P ? K : never가 경우 2)만 추출하는 경우인지를 살펴보자
경우 1)에서는 never가 나온다.
경우 2)에서는 K가 P를 확장하는 경우이다. 이때 P는 항상 string,number,symbol이고, K는 항상 string,number,symbol이 아니므로 우리가 원하는 K를 추출할 수 있다.

관련 개념

인덱스 시그니처가 사용되었다.

인덱스 시그니처의 특이한 점은 다음과 같다

  • 사실 js에서 숫자로 객체의 키에 접근하는 것은 문자열로 변경해서 접근해서 하는 것과 같다.(ex: obj[1]===obj[(1).toString()]) 그러므로 number형 인덱스 시그니처와 string형 인덱스 시그니처는 겹쳐야 한다.
  • 이와 마찬가지로 string에 대한 인덱스 시그니처가 있으면 일반 문자열을 키값으로 가진 밸류 값은 string에 대한 인덱스 시그니처와 겹쳐야 한다.
  • index-signiture는 리터럴 타입이거나, 제네릭 타입일 수 없다. 그냥 string,number,symbol으로 이뤄진 타입만 사용할 수 있다.

참고자료

https://github.com/type-challenges/type-challenges/issues/14662

https://www.typescriptlang.org/docs/handbook/2/objects.html

0개의 댓글