Passing a method class as a parameter in Typescript

I am looking for an opportunity to pass a class method to a function that can then execute this function in an instance of this class. Something like this pseudocode: (note this is an abstract example)

class Foo { public somefunc() { // do some } public anyfunc() { // do any } } function bar(obj: Foo ,func: "Foo.method") { // "that what im looking for" obj.func(); } bar(new Foo(), Foo.somefunc); // do some bar(new Foo(), Foo.anyfunc); // do any 

Is there any way to do this?

I know I could do something like this:

 class Foo { static somefunc(fooObj: Foo) { // do some } static anyfunc(fooObj: Foo) { // do any } } interface func { (fooObj: Foo); } function bar(obj: Foo, fn: func) { fn(obj); } bar(new Foo(), Foo.somefunc); // do some bar(new Foo(), Foo.anyfunc); // do any 

but it concerns static functions which I do not want.

+12
javascript function parameters typescript
Apr 23 '15 at 11:57
source share
5 answers

This does not check compilation time that the function came from Foo , but everything else:

 class Foo { public somefunc() { // do some } public anyfunc() { // do any } } function bar(obj: Foo ,func: () => void) { func.call(obj); } bar(new Foo(), Foo.prototype.somefunc); // do some bar(new Foo(), Foo.prototype.anyfunc); // do any 
+11
Apr 23 '15 at 2:48
source share

I assume that you are looking for some way for the TypeScript compiler to ensure that this function exists in Foo? Unfortunately, I don’t think there is a way to do this. Maybe another TypeScript guru might come here and answer it more specifically, but I'm sure this is the closest you can get:

 class Foo { constructor(private name:string) { } public somefunc() { console.log("someFunc called on", this.name); } public anyfunc() { console.log("anyFunc called on", this.name); } } function bar(obj: Foo, func: string) { if (obj[func] && obj[func] instanceof Function) { obj[func](); } else { throw new Error("Function '" + func + "' is not a valid function"); } } bar(new Foo("foo1"), "somefunc"); // output: 'somefunc called on foo1' bar(new Foo("foo2"), "anyfunc"); // output: 'anyfunc called on foo1' bar(new Foo("foo3"), "badFunction"); // throws: Error: Function 'badFunction' is not a valid function 
+3
Apr 23 '15 at 13:06
source share

Yes, declare the function as follows:

 myfunction(action: () => void){ action(); } 

Name it like this: typescript:

 myfunction(() => alert("hello")); 

Or from javascript:

 myfunction(function() { alert("hello"); }); 

You can also pass a method:

 myfunction(this.someMethod); 
+1
Sep 07 '16 at 9:55 on
source share

Typescript solution 2+

TL; DR : Typescript Playground , "Repo with Demo"

Benefits:

  • Check compilation time.
  • It will not allow you to lose this context if you pass an instance method.
  • Do not lose performance: you do not need to declare class methods as instance methods (for example, public somefunc = () => { return this.prop; } ) - More ....
  • Do not mess with the class prototype.
  • Agreed signature template: passing the callback as the first arg and thisArg as the second (e.g. Array.prototype.map () ).

Consider the following code:

 class Foo { private result: number = 42; public func(this: Foo): number { return this.result; } } function action(): void { console.log("Hello world!"); } function bar(callbackFn: (this: void) => any, thisArg?: undefined): any; function bar<T>(callbackFn: (this: T) => any, thisArg: T): any; function bar<T, TResult>(callbackFn: (this: T) => TResult, thisArg: T): TResult { return callbackFn.call(thisArg); } const foo = new Foo(); bar(action); // success bar(foo.func); // ERROR: forgot to pass `thisArg` bar(foo.func, foo); // success 

Turn your attention to the signature Foo#func :

 public func(this: Foo): number 

Indicates that this function should be called in the context of the class instance. This is the first part of the solution that will not let you lose this context.

The second part is the function overload bar :

 function bar(callbackFn: (this: void) => any, thisArg?: undefined): any; function bar<T>(callbackFn: (this: T) => any, thisArg: T): any; function bar<T, TResult>(callbackFn: (this: T) => TResult, thisArg: T): TResult 

This will allow you to pass common functions as well as instance methods.

You can learn more about these topics in the TypeScript Reference:

+1
Sep 16 '17 at 17:09 on
source share

Javascript would allow this, but not sure if this is what you want?

 class Foo { public someFunc(name:string){ return "Hello, " + name; } function bar(funcName: string) { return eval(funcName); } console.log(bar("new Foo().someFunc('erik')")); 
0
Apr 23 '15 at 12:33
source share



All Articles