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

xDr*_*ing 29 javascript parameters function 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
Run Code Online (Sandbox Code Playgroud)

这样做有可能吗?

我知道我可以这样做:

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
Run Code Online (Sandbox Code Playgroud)

但这涉及我不想要的静态功能.

Rya*_*ugh 20

这不是编译时检查函数是来自a 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
Run Code Online (Sandbox Code Playgroud)


Dei*_*lan 9

打字稿2+解决方案

TL; DR:TypeScript Playground,带有演示的Repo

好处:

  1. 编译时检查.
  2. this传递实例的方法时不会让你丢失上下文.
  3. 不要失去性能:不必将类'方法声明为实例方法(例如public somefunc = () => { return this.prop; }) - 了解更多信息.
  4. 不要乱用类的原型.
  5. 一致的签名模式:将回调作为第一个arg和thisArg第二个arg传递(例如Array.prototype.map()).

请考虑以下代码:

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
Run Code Online (Sandbox Code Playgroud)

把注意力转向签名Foo#func:

public func(this: Foo): number
Run Code Online (Sandbox Code Playgroud)

它声明应该在类的实例的上下文中调用此函数.这是解决方案的第一部分,它不会让您失去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
Run Code Online (Sandbox Code Playgroud)

这将允许您传递泛型函数以及实例方法.

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

  1. this 回调中的参数
  2. 功能过载
  3. 泛型


小智 5

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

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
Run Code Online (Sandbox Code Playgroud)


dev*_*evi 5

是的,像这样声明函数:

myfunction(action: () => void){
   action();
}
Run Code Online (Sandbox Code Playgroud)

从打字稿中这样称呼它:

myfunction(() => alert("hello"));
Run Code Online (Sandbox Code Playgroud)

或者从javascript:

myfunction(function() { alert("hello"); });
Run Code Online (Sandbox Code Playgroud)

你也可以通过方法:

myfunction(this.someMethod);
Run Code Online (Sandbox Code Playgroud)


Eri*_*ben -1

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

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

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

console.log(bar("new Foo().someFunc('erik')"));
Run Code Online (Sandbox Code Playgroud)