将类方法作为Typescript中的参数传递

时间:2015-04-23 11:57:48

标签: javascript function parameters typescript

我正在寻找将类方法传递给函数的可能性,然后函数可以在该类的实例上执行该函数。 像伪代码那样:(注意这是一个抽象的例子)

class Foo {
    public somefunc() {
        // do some
    }
    public anyfunc() {
        // do any
    }
}

function bar(obj: Foo ,func: "Foo.method") {  // "that's what im looking for"
    obj.func();
}

bar(new Foo(), Foo.somefunc);  // do some
bar(new Foo(), Foo.anyfunc);  // do any

是否有可能做到这一点?

我知道我可以这样做:

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

但这涉及我不想要的静态函数。

8 个答案:

答案 0 :(得分:18)

这不是编译时检查该函数是来自Foo,还是其余部分:

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

答案 1 :(得分:9)

Typescript 2+解决方案

TL; DR TypeScript PlaygroundRepo with a demo

优点:

  1. 编译时检查。
  2. 不会让你失去this上下文 传递实例的方法。
  3. 不要失去表现:不要申报课程'方法作为实例方法(例如public somefunc = () => { return this.prop; }) - Learn more
  4. 不要弄乱班级的原型。
  5. 一致的签名模式:将回调作为第一个arg传递,将thisArg作为第二个传递(例如Array.prototype.map())。
  6. 请考虑以下代码:

    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
    

    将注意力转移到Foo#func

    的签名上
    public func(this: Foo): number
    

    它声明应该在类的上下文中调用此函数。实例。这是解决方案的第一部分,它不会让您失去this上下文。

    第二部分是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
    

    这可以让你传递泛型函数和实例方法。

    您可以在TypeScript手册中了解有关这些主题的更多信息:

    1. this parameters in callbacks
    2. Function overloads
    3. Generics

答案 2 :(得分:3)

我假设您正在寻找TypeScript编译器的某种方式来强制Foo上存在给定的函数?不幸的是,我认为没有办法做到这一点。也许另一个TypeScript大师可以进来并更具体地回答,但我很确定这是你能得到的最接近的:

AppCompatActivity

答案 3 :(得分:2)

Javascript会允许这样做,但不确定这是否是你想要的?

class Foo {
 public someFunc(name:string){
  return "Hello, " + name;
 }

function bar(funcName: string) {
    return eval(funcName);
}

console.log(bar("new Foo().someFunc('erik')"));

答案 4 :(得分:1)

是的,声明这样的功能:

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

从typescript中调用它:

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

或者来自javascript:

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

你也可以传递方法:

myfunction(this.someMethod);

答案 5 :(得分:1)

就我而言;根据问题的陈述,我本可以这样做:

class Foo {
    public constructor() {
        this.welcome = this.welcome.bind(this)
    }

    public welcome(msg: string): void {
        console.log(`hello ${msg}`)
    }
}

function bar(msg: string, fn: void): void {
    fn(msg)
}

const foo = new Foo()
bar('world', foo.welcome) // 'hello world'

此外,我应该指出,我受到this clear explanation的启发。

希望有帮助!

答案 6 :(得分:1)

您可以使用粗箭头功能。他们不应该失去“这个”

class Foo {
    public somefunc = () => {
        // do some
    }
    public anyfunc = () => {
        // do any
    }
}

答案 7 :(得分:0)

我认为,在这种情况下,您应该使用立面设计模式。

创建复杂的库,工具或系统时,包含许多功能和/或类;它变得难以理解和依赖。因此,您应该实现一个提供简单统一接口的类。

class Foo{

      public somefunc() {
        console.log("some")
      }

      public anyfunc() {
        console.log("any")
      }


    };


    class FuncFacade {

      getFunc(obj: any, func_name: string) {
        switch (func_name) {
          case obj.somefunc.name: {
            return obj.somefunc;
          }

          case obj.anyfunc.name: {
            return obj.anyfunc;
          }
          default: {
            throw new Error("No such func!");
          }

        }
      }
    }

    let ff = new FuncFacade();

    function bar(obj: Foo, func_name: string) {
      ff.getFunc(obj,func_name)();
    }

    bar(new Foo(), Foo.prototype.anyfunc.name);

也许这不是您要的,但这就是应该的方式。