Given an interface (from an existing .d.ts file that can't be changed):
interface Foo {
  [key: string]: any;
  bar(): void;
}
Is there a way to use mapped types (or another method) to derive a new type without the index signature? i.e. it only has the method bar(): void;
Edit: Since Typescript 4.1 there is a way of doing this directly with Key Remapping, avoiding the Pick combinator. Please see the answer by Oleg where it's introduced.
type RemoveIndex<T> = {   [ K in keyof T as string extends K ? never : number extends K ? never : K ] : T[K] };  It is based on the fact that 'a' extends string but string doesn't extends 'a'.
There is also a way to express that with TypeScript 2.8's Conditional Types.
interface Foo {   [key: string]: any;   [key: number]: any;   bar(): void; }  type KnownKeys<T> = {   [K in keyof T]: string extends K ? never : number extends K ? never : K } extends { [_ in keyof T]: infer U } ? U : never;   type FooWithOnlyBar = Pick<Foo, KnownKeys<Foo>>;  You can make a generic out of that:
// Generic !!! type RemoveIndex<T extends Record<any,any>> = Pick<T, KnownKeys<T>>;  type FooWithOnlyBar = RemoveIndex<Foo>;  For an explanation of why exactly KnownKeys<T> works, see the following answer:
https://stackoverflow.com/a/51955852/2115619
With TypeScript v4.1 key remapping leads to a very concise solution.
At its core it uses a slightly modified logic from Mihail's answer: while a known key is a subtype of either string or number, the latter are not subtypes of the corresponding literal. On the other hand, string is a union of all possible strings (the same holds true for number) and thus is reflexive (type res = string extends string ? true : false; //true holds).
This means you can resolve to never every time the type string or number is assignable to the type of key, effectively filtering it out:
interface Foo {
  [key: string]: any;
  [key: number]: any;
  bar(): void;
}
type RemoveIndex<T> = {
  [ P in keyof T as string extends P ? never : number extends P ? never : P ] : T[P]
};
type FooWithOnlyBar = RemoveIndex<Foo>; //{ bar: () => void; }
Playground
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With