2015-04-23 198 views
13

我正在尋找將類方法傳遞給函數的可能性,然後該函數可以在該類的一個實例上執行該函數。 類似的東西僞代碼:(注意,這是一個抽象的例子)在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 

,但涉及我不想靜態函數。

回答

0

JavaScript會允許這個,但不知道如果這是你想要的?

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

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

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

是啊,那會的工作,但我不會打字稿的好處檢查'Foo'上是否實際定義了'someFunc()'。 – xDreamCoding

3

我假設你正在尋找某種方式讓TypeScript編譯器強制給定的函數存在於Foo上?不幸的是,我認爲沒有辦法做到這一點。也許另一個打字稿大師能進來這裏,並回答更具體,但我敢肯定,這是你可以得到的最接近:

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 
+0

你是對的,我希望打字稿能讓編譯器檢查這個給定函數是否存在於類中。 感謝您的答案,但不知道你可以調用這樣的對象的函數:'obj [「functionname」]()' – xDreamCoding

+0

真棒的答案。非常感謝 – suku

12

這並不編譯時檢查函數從進來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

是,聲明函數是這樣的:

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

這樣調用它從打字稿:

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

或者從JavaScript:

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

您也可以通過方法:

myfunction(this.someMethod); 
1

打字稿2+解決方案

TL; DRTypeScript PlaygroundRepo with a demo

優點:

  1. 編譯時檢查。
  2. 當 傳遞實例的方法時,不會讓你丟失this上下文。
  3. 不要失去表現:不必將類的方法聲明爲實例方法(例如public somefunc =() => { return this.prop; }) - Learn more
  4. 不要混淆類的原型。
  5. 一致的簽名模式:將回調作爲第一參數傳遞,並將thisArg作爲第二參數(例如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 

將注意力轉移到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 

這會讓你你通過通用的功能以及實例方法。

您可以瞭解更多有關這些主題在打字稿手冊:

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