본문 바로가기
Language/Typescript

타입챌린지 : 1367-Remove Index Signature (medium)

by hsloth 2023. 4. 24.

 

이 글은 제가 타입챌린지를 하면서 해석한 내용을 적는 글입니다. 틀린 내용이 있으면 댓글 달아주시면 감사하겠습니다.

 

https://github.com/type-challenges/type-challenges/blob/main/questions/01367-medium-remove-index-signature/README.md

 

GitHub - type-challenges/type-challenges: Collection of TypeScript type challenges with online judge

Collection of TypeScript type challenges with online judge - GitHub - type-challenges/type-challenges: Collection of TypeScript type challenges with online judge

github.com

 

제네릭에 인자로 받아온 타입의 Index Signature를 제거하여 리턴하는 타입이다.

일단, 나는 Index Signature라는게 뭔지 몰라서 검색해봤다.

간단하게 말하면, [key: T]: U 형식으로 객체가 여러 key를 가질 수 있도록 하기위해 사용하는 것이었다.

 

추가설명으로, 특징이 있다면 key의 타입으로 number, string, symbol과 number, string, symbol로 이루어진 Template literal type만 올 수 있다는 것이다. (Template literal type은 정해진 값으로 이루어진 타입을 말한다.)

 

그래서.. 위의 key값이 number, string, symbol에 해당하는지만 걸러주면 된다.

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


/* _____________ Test Cases _____________ */
import type { Equal, Expect } from '@type-challenges/utils'

type Foo = {
  [key: string]: any
  foo(): void
}

type Bar = {
  [key: number]: any
  bar(): void
  0: string
}

const foobar = Symbol('foobar')
type FooBar = {
  [key: symbol]: any
  [foobar](): void
}

type Baz = {
  bar(): void
  baz: string
}

생각보다 간단하다.

Foo의 key값을 보면, string과 "foo"가 있다. Index Signature를 사용하므로 key값에 string과 같은 타입이 오는 것이다.

그리고, "foo" extends string은 true지만, string extends "foo"는 false인 것을 이용하여 걸러주면 된다.

자세한 설명은 생략하겠다.

 

참고로, type Foobar에서 [foobar](): void는 위의 const foobar = Symbol('foobar') 로 정의된 번수를 함수 명으로 사용할 수 있도록 한 문법이다. 아마 함수 명을 변수로 사용하고 싶을 때 사용하는 듯 하다.