Javascript 在Typescript中将类方法作为参数传递
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/29822773/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Passing class method as parameter in Typescript
提问by xDreamCoding
I'm searching for a possibility to pass a class-method to a function which then can execute that function on an instance of that class. Something like that pseudocode: (note that this is an abstract example)
我正在寻找将类方法传递给函数的可能性,然后该函数可以在该类的实例上执行该函数。类似于那个伪代码:(注意这是一个抽象的例子)
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
Is there a possiblity to do this?
有没有可能做到这一点?
I know i could be doing something like that:
我知道我可以做这样的事情:
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
but that involves static functions which I don't want.
但这涉及我不想要的静态函数。
回答by Ryan Cavanaugh
This doesn't compile-time check that the function came from a Foo, but does the rest:
这不会在编译时检查函数是否来自 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
回答by Deilan
Typescript 2+ solution
打字稿 2+ 解决方案
TL;DR: TypeScript Playground, Repo with a demo
TL;DR: TypeScript Playground, Repo with a demo
Advantages:
好处:
- Compile-time checking.
- Won't let you lost
thiscontext when passing an instance's method. - Don't lose performance: don't have to declare class' methods as instance methods (e. g.
public somefunc = () => { return this.prop; }) - Learn more. - Don't mess with a class's prototype.
- Consistent signature pattern: passing a callback as the first arg and
thisArgas the second (e. g. Array.prototype.map()).
- 编译时检查。
this传递实例的方法时不会让您丢失上下文。- 不要失去性能:不必将类的方法声明为实例方法(例如
public somefunc = () => { return this.prop; }) -了解更多。 - 不要弄乱类的原型。
- 一致的签名模式:将回调作为第一个参数和
thisArg第二个参数(例如Array.prototype.map())传递。
Consider the following code:
考虑以下代码:
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
Turn your attention to the signature of Foo#func:
将注意力转移到以下签名上Foo#func:
public func(this: Foo): number
It states that this function should be invoked in a context of the class' instance. This is the first part of the solution which won't let you lost thiscontext.
它指出这个函数应该在类的实例的上下文中调用。这是解决方案的第一部分,不会让您失去this上下文。
The second part is barfunction overloads:
第二部分是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
This would let you you pass generic functions as well as instance methods.
这将使您可以传递通用函数以及实例方法。
You can learn more about these topics in TypeScript Handbook:
您可以在 TypeScript 手册中了解有关这些主题的更多信息:
回答by devi
Yes, declare function like this:
是的,像这样声明函数:
myfunction(action: () => void){
action();
}
Call it like this from typescript:
从打字稿中这样称呼它:
myfunction(() => alert("hello"));
Or from javascript:
或者从javascript:
myfunction(function() { alert("hello"); });
Also you can pass method:
你也可以通过方法:
myfunction(this.someMethod);
回答by thetoast
I'm assuming you're looking for some way for the TypeScript compiler to enforce that the given function exists on Foo? Unfortunately, I don't think there's a way to do that. Maybe another TypeScript guru can come in here and answer that more concretely, but I'm pretty sure this is the closest that you can get:
我假设您正在寻找某种方式让 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
回答by Clément MARTZLOFF
For my part; according to the statement of the problem, I could have done like this:
对我来说; 根据问题的陈述,我可以这样做:
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'
In addition, I should point out that I was inspired by this clear explanation.
此外,我应该指出,我受到了这个清晰解释的启发。
Hope it helps !
希望能帮助到你 !
回答by Erik Lieben
Javascript would allow this, but not sure if that is what you want?
Javascript 会允许这样做,但不确定这是否是您想要的?
class Foo {
public someFunc(name:string){
return "Hello, " + name;
}
function bar(funcName: string) {
return eval(funcName);
}
console.log(bar("new Foo().someFunc('erik')"));

