I want to dynamically call methods by a variable name in typescript, as shown in the following example.
function callMethod(_class, method: string){
let classObj = new _class();
return classObj[method]()
}
the previous code snippet has no real benefits, but it can obviously explain the idea with a minimal code.
however, if you enabled the option noImplicitAny in tsconfig.json, you have to add a type annotation
return classObj[method as keyof typeof classObj]()
Theoretically, it works fine in Js, but ts complains that not all constituents are callable, and shows this error:
This expression is not callable.
Not all constituents of type ... are callable.
how can I dynamically call a method in typescript?
If you make the method, the class, and the static part of the class all generic, you can do something like this:
function callMethod<
M extends PropertyKey,
C extends {[K in M]: () => any},
T extends {new(): C}
>(_class: T, method: M): ReturnType<InstanceType<T>[M]> {
const classObj = new _class();
return classObj[method]()
}
class Test {
someMethod(): number { return 8}
}
const t1 = callMethod(Test, 'someMethod') // Inferred type: number.
const t2: string = callMethod(Test, 'someMethod')
// ERROR: .. Type 'number' is not assignable to type 'string'.
const t3 = callMethod(Test, 'noMethod')
// ERROR: .. Property 'noMethod' is missing in type 'Test' but required in
// type '{ noMethod: () => unknown; }'.
TypeScript playground
Inside callMethod the return type of method will be any, but typing this to a fourth type parameter and getting it to agree with ReturnType<InstanceType<T>[M]> seems tricky (and might not be possible). As long as you directly return the result of the method call, this shouldn't be too much of an issue though.
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