# 1367-移除索引签名

# 题目描述

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 }

# 分析

索引签名,其实在 元组转联合 中提到过,其更多定义可以在 Index Signatures (opens new window) 找到。

要想移除索引签名,可以看看如下示例:

type Foo = {
  [key: string]: any;
  0: 1;
  test: 1;
  [key: number]: any;
  [key: symbol]: any;
  foo(): void;
};

/*
Case1 = {
    [x: string]: string;
    [x: number]: number;
    [x: symbol]: symbol;
    0: 0;
    test: "test";
    foo: "foo";
}
*/

type Case1 = {
  [P in keyof Foo]: P;
};

可以看出来,所谓的索引签名,核心就在于它的 key 是 string | number | symbol,而不是像 Case1 中 0 | 'test' | 'foo' 这样的常量

根据这一点,借助类似 实现 Omit 中的 as 操作符,就可以把 string | number | symbol 这样的索引签名过滤掉。

# 题解

type isStringNumberSymbol<T> = string extends T
  ? never
  : number extends T
  ? never
  : symbol extends T
  ? never
  : T;

type RemoveIndexSignature<T> = {
  [P in keyof T as isStringNumberSymbol<P>]: T[P];
};

只要是 P 是 string | number | symbol 中的一个,就返回 never,从而过滤掉索引签名的 key。

注意这里用的是 string extends T 而不是 T extends string,值得细品。

# 知识点

  1. 索引签名的本质,其 key 的类型是 string | number | symbol,注意不是其子类型,普通的 key 是常量 而非类型本身
Last Updated: 2023/5/16 06:00:28