Home > Mobile >  How do I get parameter type for a function in a type containing only functions
How do I get parameter type for a function in a type containing only functions

Time:09-17

I want to create a generic function that only allows calls to functions specified in an interface.

interface MyApi {
    add(x: number, y:number) : number;
    say(s:string): string;
    A: number;
}

type OnlyFuncs<T> = Pick<T, { [K in keyof T]: T[K] extends (...args:any) => any ? K : never }[keyof T]>;
    
class ApiClient<T, Tfunc = OnlyFuncs<T>> {
    public call<K extends keyof Tfunc, T2 = Tfunc[K]>(method:K, p:Parameters<T2>) {

    }
}

I'd like to able to use my ApiClient class to call the two methods 'add' and 'say' from the function 'call'. I've managed to "filter out" member A from the MyApi interface, but I can't get the correct type T2 to get the parameters right for the 'p' argument.

Why is T2 not seen by the compiler as a function?

CodePudding user response:

You just need to constrain the object type represented by your generic T:

TS Playground

type AnyFn = (...args: any) => any;
type AnyObj = Record<PropertyKey, any>;

type OnlyFuncs<T extends AnyObj> = {
  [K in keyof T as T[K] extends AnyFn ? K : never]: T[K];
};

interface MyApi {
  add(x: number, y: number) : number;
  say(s: string): string;
  A: number;
}

class ApiClient<T extends AnyObj> {
  public call<K extends keyof OnlyFuncs<T>>(
    method: K,
    p: Parameters<T[K]>,
  ) {}
}

const client = new ApiClient<MyApi>();
client.call('say', ['hello']);
client.call('add', [2, 3]);

client.call('A', []); /*
            ~~~
Argument of type '"A"' is not assignable to parameter of type '"say" | "add"'.(2345) */

type AllowedMethod = Parameters<typeof client.call>[0];
   //^? type AllowedMethod = "say" | "add"

  • Related