題目
中文
實現 RemoveIndexSignature<T>
, 將索引字段從對象中排除掉.
示例:
type Foo = {
[key: string]: any;
foo(): void;
};
type A = RemoveIndexSignature<Foo>; // expected { foo(): void }
English
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 }
答案
type RemoveIndexSignature<T extends object> = {
[P in keyof T as string extends P
? never
: number extends P
? never
: symbol extends P
? never
: P]: T[P];
};
解析
關鍵在於理解當對一個包含索引簽名(Index Signature
)的對象類型執行keyof
會返回什麼, 看下面幾個例子:
type Foo = keyof { [key: string]: any }; // Foo 的類型是 string | number
type Bar = keyof { [key: symbol]: any }; // Bar 的類型是 symbol
type FooBar = keyof { [key: string | number | symbol]: any }; // FooBar 的類型是 string | number | symbol
type FooFoo = keyof { name: string; age: string }; // FooFoo的類型是 'name' | 'age'
keyof
某個對象時, 對象中普通的字段會變成字面量類型, 對應上面例子中的FooFoo
, 而索引簽名會變成 string number symbol 這些類型組合出來的聯合類型, 知道了這點就可以判斷是否爲索引簽名了
type isIndexSignature<T> = string extends T
? true
: number extends T
? true
: symbol extends T
? true
: false;