2015-04-23 20 views
13

Ich suche nach einer Möglichkeit, eine Klassenmethode an eine Funktion zu übergeben, die dann diese Funktion für eine Instanz dieser Klasse ausführen kann. etwas wie der Pseudo-Code: (beachten Sie, dass dies ein abstraktes Beispiel)Klassenmethode als Parameter übergeben in 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 

Gibt es eine Möglichkeit, dies zu tun?

Ich weiß, dass ich so etwas tun könnte:

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 

aber das beinhaltet statische Funktionen, die ich nicht will.

Antwort

0

Javascript würde dies erlauben, aber nicht sicher, ob das was du willst?

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

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

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

Ja, das funktionieren würde, aber ich würde nicht in den Genuss von Typoskript bekommen Überprüfen, ob 'someFunc()' tatsächlich auf 'Foo' definiert ist. – xDreamCoding

3

Ich nehme an, Sie für den Typoskript Compiler für irgendeine Weise gesuchte zu erzwingen, dass die gegebene Funktion auf Foo existiert? Leider glaube ich nicht, dass es einen Weg dafür gibt. Vielleicht kann ein anderer Typoskript Guru kommen hier in und antworten, dass konkreter, aber ich bin mir ziemlich sicher, dass diese am nächsten ist, die Sie bekommen können:

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

Sie haben recht, ich hatte gehofft, in Typoskript war eine Möglichkeit, den Compiler zu überprüfen, ob diese bestimmte Funktion in der Klasse vorhanden ist. Vielen Dank für die Antwort, wusste nicht, dass Sie eine Funktion eines Objekts wie folgt aufrufen können: 'obj [" Funktionsname "]()' – xDreamCoding

+0

Awesome Antwort. Danke vielmals – suku

12

Dies gilt nicht kompilieren Zeit prüfen, ob die Funktion von a kam Foo, aber erledigt den Rest:

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

Ja, Funktion wie folgt erklären:

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

Nennen sie es, wie dies aus Typoskript:

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

Oder von javascript:

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

Sie können auch Methode übergeben:

myfunction(this.someMethod); 
1

Typoskript 2+ -Lösung

TL; DR: TypeScript Playground, Repo with a demo

Vorteile:

  1. Überprüfung der Kompilierzeit.
  2. Lassen Sie sich nicht verlieren this Kontext, wenn die Methode einer Instanz übergeben.
  3. Keine Leistungseinbußen: Klassenmethoden müssen nicht als Instanzmethoden deklariert werden (z. B. public somefunc =() => { return this.prop; }) - Learn more.
  4. Verwechseln Sie nicht den Prototyp einer Klasse.
  5. Konsistentes Signaturmuster: einen Rückruf als erstes Argument übergeben und thisArg als zweites Argument (z. B. Array.prototype.map()).

Betrachten Sie den folgenden Code ein:

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 

zur Unterzeichnung Foo#func Verwandeln Sie Ihre Aufmerksamkeit:

public func(this: Foo): number 

Darin heißt es, dass diese Funktion sollte in einem Kontext der Klasse aufgerufen werden Instanz . Dies ist der erste Teil der Lösung, der Sie nicht verloren gehen wird.

Der zweite Teil ist bar Funktion Überlastungen:

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 

Dies würden Sie lassen Sie generische Funktionen sowie Instanz Methoden übergeben.

Sie können mehr über diese Themen in Typoskript Handbuch lernen:

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