[Typescript] 42. Medium - Remove Index Signature

Implement RemoveIndexSignature<T> , exclude the index signature from object types.

For example:

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

type A = RemoveIndexSignature<Foo>  // expected { foo(): void }

Interesting, so it turns out that they represent any key on the object as a string type literal. While the index signature has just a type like number or string.

It leads me to the idea that we need to filter out any keys that are not type literals. But, how do we check if the type is a type literal or not? We can use the nature of sets and check if some set is a subset or not. For instance, the type literal “foo” extends from the string, but not otherwise, “foo” is too narrow to be a string.

"foo" extends string // true
string extends "foo" // false

 

/* _____________ Your Code Here _____________ */

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
}

type cases = [
  Expect<Equal<RemoveIndexSignature<Foo>, { foo(): void }>>,
  Expect<Equal<RemoveIndexSignature<Bar>, { bar(): void; 0: string }>>,
  Expect<Equal<RemoveIndexSignature<FooBar>, { [foobar](): void }>>,
  Expect<Equal<RemoveIndexSignature<Baz>, { bar(): void; baz: string }>>,
]
type TypeLiteralOnly<T> = string extends T
  ? never
  : number extends T
  ? never
  : T;
type RemoveIndexSignature<T> = { [P in keyof T as TypeLiteralOnly<P>]: T[P] };

 

posted @ 2022-10-05 01:17  Zhentiw  阅读(58)  评论(0编辑  收藏  举报