Je cherche une possibilité de passer une méthode de classe à une fonction qui peut ensuite exécuter cette fonction sur une instance de cette classe. Quelque chose comme ce pseudocode: (notez que c'est un exemple abstrait)
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
Y a-t-il une possibilité de le faire?
Je sais que je pourrais faire quelque chose comme ça:
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
mais cela implique des fonctions statiques dont je ne veux pas.
Cela ne vérifie pas à la compilation que la fonction provenait d'un Foo
, mais fait le reste:
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
TL; DR : TypeScript Playground , Repo avec une démo
Avantages:
this
lors du passage de la méthode d'une instance.public somefunc = () => { return this.prop; }
) - En savoir plus .thisArg
comme deuxième (par exemple Array.prototype.map () ).Considérez le code suivant:
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
Portez votre attention sur la signature de Foo#func
:
public func(this: Foo): number
Il indique que cette fonction doit être invoquée dans un contexte d'instance de classe. C'est la première partie de la solution qui ne vous laissera pas perdre le contexte this
.
La deuxième partie est bar
surcharge de fonction:
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
Cela vous permettrait de passer des fonctions génériques ainsi que des méthodes d'instance.
Vous pouvez en savoir plus sur ces sujets dans le manuel TypeScript:
Je suppose que vous cherchez un moyen pour le compilateur TypeScript de faire en sorte que la fonction donnée existe sur Foo? Malheureusement, je ne pense pas qu'il y ait moyen de le faire. Peut-être qu'un autre gourou de TypeScript peut venir ici et y répondre plus concrètement, mais je suis presque sûr que c'est le plus proche que vous pouvez obtenir:
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
Oui, déclarez une fonction comme celle-ci:
myfunction(action: () => void){
action();
}
Appelez-le comme ceci à partir de TypeScript:
myfunction(() => alert("hello"));
Ou depuis javascript:
myfunction(function() { alert("hello"); });
Vous pouvez également passer la méthode:
myfunction(this.someMethod);
Javascript permettrait cela, mais vous ne savez pas si c'est ce que vous voulez?
class Foo {
public someFunc(name:string){
return "Hello, " + name;
}
function bar(funcName: string) {
return eval(funcName);
}
console.log(bar("new Foo().someFunc('erik')"));