vendredi 17 septembre 2021

Typescript get type of only callable/executable members

I have a class with mixed member types, fields and methods (ex. MyClass below). I am trying to have a command created that calls a function and is able to execute it while keeping this context.

The code below works if I use a class that has no fields in it, only callable members ( ex. if i comment out public field: number = 1;) This works fine, good type sense, errors if class method does not exist, errors if bad params. but it kind of does not like it when i pass a class that has non-callable members. Maybe you guys have a solution for that?

TS playground example

class MyClass{
  constructor() {}
  
  public field: number = 1;

  public printMessage(): void{
    console.log("message")
  }
  public printNumber(i: number): number{
    return i;
  }
}

type TypeOfClassMethod<T, M extends keyof T> = T[M] extends Function ? T[M] : never;

interface ICommand{

    execute(): any;
}

 class Command<F extends keyof MyClass> implements ICommand{
    api: MyClass;

    constructor(
        api: MyClass, 
        private func: TypeOfClassMethod<MyClass, F>, 
        private args:  Parameters<TypeOfClassMethod<MyClass, F>> //
        ) {
        this.api = api;
    }
    
    execute():  ReturnType<TypeOfClassMethod<MyClass, F>>{ 
 // error[1] type ‘TypeOfClassMethod<MyClass, F>’ does not satisfy the constraint ‘(...args: any) => any’.
 // Type ‘Function & MyClass[F]’ is not assignable to type ‘(...args: any) => any’.
        return this.func.call(this.api, ...this.args)
    }
}


let instance = new MyClass();

const command = new Command<"printNumber">(instance, instance.printNumber, [5] );
const wrongCOmmand = new Command<"field">(instance, instance.field, [] );

Aucun commentaire:

Enregistrer un commentaire